X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Faacraid%2Flinit.c;h=d2cf875af59b6139fa99f63257b1e189fc22551a;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=c552191428cfba1f2f70c09d0c37634ded631869;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index c55219142..d2cf875af 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -27,9 +27,6 @@ * Abstract: Linux Driver entry module for Adaptec RAID Array Controller */ -#define AAC_DRIVER_VERSION "1.1.2-lk2" -#define AAC_DRIVER_BUILD_DATE __DATE__ -#define AAC_DRIVERNAME "aacraid" #include #include @@ -42,8 +39,11 @@ #include #include #include +#include #include -#include +#include +#include +#include #include #include @@ -56,25 +56,33 @@ #include "aacraid.h" +#define AAC_DRIVER_VERSION "1.1-5" +#ifndef AAC_DRIVER_BRANCH +#define AAC_DRIVER_BRANCH "" +#endif +#define AAC_DRIVER_BUILD_DATE __DATE__ " " __TIME__ +#define AAC_DRIVERNAME "aacraid" + +#ifdef AAC_DRIVER_BUILD +#define _str(x) #x +#define str(x) _str(x) +#define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION "[" str(AAC_DRIVER_BUILD) "]" AAC_DRIVER_BRANCH +#else +#define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION AAC_DRIVER_BRANCH " " AAC_DRIVER_BUILD_DATE +#endif MODULE_AUTHOR("Red Hat Inc and Adaptec"); MODULE_DESCRIPTION("Dell PERC2, 2/Si, 3/Si, 3/Di, " "Adaptec Advanced Raid Products, " - "and HP NetRAID-4M SCSI driver"); + "HP NetRAID-4M, IBM ServeRAID & ICP SCSI driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(AAC_DRIVER_FULL_VERSION); - -int nondasd = -1; -module_param(nondasd, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on"); - -int paemode = -1; -module_param(paemode, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(paemode, "Control whether dma addressing is using PAE. 0=off, 1=on"); - -struct aac_dev *aac_devices[MAXIMUM_NUM_ADAPTERS]; -static unsigned aac_count; +static LIST_HEAD(aac_devices); static int aac_cfg_major = -1; +char aac_driver_version[] = AAC_DRIVER_FULL_VERSION; + +extern int expose_physicals; /* * Because of the way Linux names scsi devices, the order in this table has @@ -83,44 +91,72 @@ static int aac_cfg_major = -1; * Note: The last field is used to index into aac_drivers below. */ static struct pci_device_id aac_pci_tbl[] = { - { 0x1028, 0x0001, 0x1028, 0x0001, 0, 0, 0 }, /* PERC 2/Si */ - { 0x1028, 0x0002, 0x1028, 0x0002, 0, 0, 1 }, /* PERC 3/Di */ - { 0x1028, 0x0003, 0x1028, 0x0003, 0, 0, 2 }, /* PERC 3/Si */ - { 0x1028, 0x0004, 0x1028, 0x00d0, 0, 0, 3 }, /* PERC 3/Si */ - { 0x1028, 0x0002, 0x1028, 0x00d1, 0, 0, 4 }, /* PERC 3/Di */ - { 0x1028, 0x0002, 0x1028, 0x00d9, 0, 0, 5 }, /* PERC 3/Di */ - { 0x1028, 0x000a, 0x1028, 0x0106, 0, 0, 6 }, /* PERC 3/Di */ - { 0x1028, 0x000a, 0x1028, 0x011b, 0, 0, 7 }, /* PERC 3/Di */ - { 0x1028, 0x000a, 0x1028, 0x0121, 0, 0, 8 }, /* PERC 3/Di */ - { 0x9005, 0x0283, 0x9005, 0x0283, 0, 0, 9 }, /* catapult*/ - { 0x9005, 0x0284, 0x9005, 0x0284, 0, 0, 10 }, /* tomcat*/ - { 0x9005, 0x0285, 0x9005, 0x0286, 0, 0, 11 }, /* Adaptec 2120S (Crusader)*/ - { 0x9005, 0x0285, 0x9005, 0x0285, 0, 0, 12 }, /* Adaptec 2200S (Vulcan)*/ - { 0x9005, 0x0285, 0x9005, 0x0287, 0, 0, 13 }, /* Adaptec 2200S (Vulcan-2m)*/ - { 0x9005, 0x0285, 0x17aa, 0x0286, 0, 0, 14 }, /* Legend S220*/ - { 0x9005, 0x0285, 0x17aa, 0x0287, 0, 0, 15 }, /* Legend S230*/ - - { 0x9005, 0x0285, 0x9005, 0x0288, 0, 0, 16 }, /* Adaptec 3230S (Harrier)*/ - { 0x9005, 0x0285, 0x9005, 0x0289, 0, 0, 17 }, /* Adaptec 3240S (Tornado)*/ - { 0x9005, 0x0285, 0x9005, 0x028a, 0, 0, 18 }, /* ASR-2020 ZCR PCI-X U320 */ - { 0x9005, 0x0285, 0x9005, 0x028b, 0, 0, 19 }, /* ASR-2025 ZCR DIMM U320 */ - { 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 20 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II)*/ - - { 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 21 }, /* Perc 320/DC*/ - { 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 22 }, /* Adaptec 5400S (Mustang)*/ - { 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 23 }, /* Adaptec 5400S (Mustang)*/ - { 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 24 }, /* Dell PERC2 "Quad Channel" */ - { 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 25 }, /* HP NetRAID-4M */ - - { 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 26 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */ - { 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 27 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ - { 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 28 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ - { 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 29 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */ - { 0x9005, 0x0285, 0x0E11, 0x0295, 0, 0, 30 }, /* SATA 6Ch (Bearcat) */ - - { 0x9005, 0x0286, 0x9005, 0x028c, 0, 0, 31 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */ - { 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 32 }, /* ASR-2020SA (ZCR PCI-X SATA) */ - { 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 33 }, /* ASR-2025SA (ZCR DIMM SATA) */ + { 0x1028, 0x0001, 0x1028, 0x0001, 0, 0, 0 }, /* PERC 2/Si (Iguana/PERC2Si) */ + { 0x1028, 0x0002, 0x1028, 0x0002, 0, 0, 1 }, /* PERC 3/Di (Opal/PERC3Di) */ + { 0x1028, 0x0003, 0x1028, 0x0003, 0, 0, 2 }, /* PERC 3/Si (SlimFast/PERC3Si */ + { 0x1028, 0x0004, 0x1028, 0x00d0, 0, 0, 3 }, /* PERC 3/Di (Iguana FlipChip/PERC3DiF */ + { 0x1028, 0x0002, 0x1028, 0x00d1, 0, 0, 4 }, /* PERC 3/Di (Viper/PERC3DiV) */ + { 0x1028, 0x0002, 0x1028, 0x00d9, 0, 0, 5 }, /* PERC 3/Di (Lexus/PERC3DiL) */ + { 0x1028, 0x000a, 0x1028, 0x0106, 0, 0, 6 }, /* PERC 3/Di (Jaguar/PERC3DiJ) */ + { 0x1028, 0x000a, 0x1028, 0x011b, 0, 0, 7 }, /* PERC 3/Di (Dagger/PERC3DiD) */ + { 0x1028, 0x000a, 0x1028, 0x0121, 0, 0, 8 }, /* PERC 3/Di (Boxster/PERC3DiB) */ + { 0x9005, 0x0283, 0x9005, 0x0283, 0, 0, 9 }, /* catapult */ + { 0x9005, 0x0284, 0x9005, 0x0284, 0, 0, 10 }, /* tomcat */ + { 0x9005, 0x0285, 0x9005, 0x0286, 0, 0, 11 }, /* Adaptec 2120S (Crusader) */ + { 0x9005, 0x0285, 0x9005, 0x0285, 0, 0, 12 }, /* Adaptec 2200S (Vulcan) */ + { 0x9005, 0x0285, 0x9005, 0x0287, 0, 0, 13 }, /* Adaptec 2200S (Vulcan-2m) */ + { 0x9005, 0x0285, 0x17aa, 0x0286, 0, 0, 14 }, /* Legend S220 (Legend Crusader) */ + { 0x9005, 0x0285, 0x17aa, 0x0287, 0, 0, 15 }, /* Legend S230 (Legend Vulcan) */ + + { 0x9005, 0x0285, 0x9005, 0x0288, 0, 0, 16 }, /* Adaptec 3230S (Harrier) */ + { 0x9005, 0x0285, 0x9005, 0x0289, 0, 0, 17 }, /* Adaptec 3240S (Tornado) */ + { 0x9005, 0x0285, 0x9005, 0x028a, 0, 0, 18 }, /* ASR-2020ZCR SCSI PCI-X ZCR (Skyhawk) */ + { 0x9005, 0x0285, 0x9005, 0x028b, 0, 0, 19 }, /* ASR-2025ZCR SCSI SO-DIMM PCI-X ZCR (Terminator) */ + { 0x9005, 0x0286, 0x9005, 0x028c, 0, 0, 20 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */ + { 0x9005, 0x0286, 0x9005, 0x028d, 0, 0, 21 }, /* ASR-2130S (Lancer) */ + { 0x9005, 0x0286, 0x9005, 0x029b, 0, 0, 22 }, /* AAR-2820SA (Intruder) */ + { 0x9005, 0x0286, 0x9005, 0x029c, 0, 0, 23 }, /* AAR-2620SA (Intruder) */ + { 0x9005, 0x0286, 0x9005, 0x029d, 0, 0, 24 }, /* AAR-2420SA (Intruder) */ + { 0x9005, 0x0286, 0x9005, 0x029e, 0, 0, 25 }, /* ICP9024RO (Lancer) */ + { 0x9005, 0x0286, 0x9005, 0x029f, 0, 0, 26 }, /* ICP9014RO (Lancer) */ + { 0x9005, 0x0286, 0x9005, 0x02a0, 0, 0, 27 }, /* ICP9047MA (Lancer) */ + { 0x9005, 0x0286, 0x9005, 0x02a1, 0, 0, 28 }, /* ICP9087MA (Lancer) */ + { 0x9005, 0x0286, 0x9005, 0x02a3, 0, 0, 29 }, /* ICP5445AU (Hurricane44) */ + { 0x9005, 0x0285, 0x9005, 0x02a4, 0, 0, 30 }, /* ICP9085LI (Marauder-X) */ + { 0x9005, 0x0285, 0x9005, 0x02a5, 0, 0, 31 }, /* ICP5085BR (Marauder-E) */ + { 0x9005, 0x0286, 0x9005, 0x02a6, 0, 0, 32 }, /* ICP9067MA (Intruder-6) */ + { 0x9005, 0x0287, 0x9005, 0x0800, 0, 0, 33 }, /* Themisto Jupiter Platform */ + { 0x9005, 0x0200, 0x9005, 0x0200, 0, 0, 33 }, /* Themisto Jupiter Platform */ + { 0x9005, 0x0286, 0x9005, 0x0800, 0, 0, 34 }, /* Callisto Jupiter Platform */ + { 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 35 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */ + { 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 36 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */ + { 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 37 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */ + { 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 38 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */ + { 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 39 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ + { 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 40 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ + { 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 41 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */ + { 0x9005, 0x0285, 0x103C, 0x3227, 0, 0, 42 }, /* AAR-2610SA PCI SATA 6ch */ + { 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 43 }, /* ASR-2240S (SabreExpress) */ + { 0x9005, 0x0285, 0x9005, 0x0297, 0, 0, 44 }, /* ASR-4005 */ + { 0x9005, 0x0285, 0x1014, 0x02F2, 0, 0, 45 }, /* IBM 8i (AvonPark) */ + { 0x9005, 0x0285, 0x1014, 0x0312, 0, 0, 45 }, /* IBM 8i (AvonPark Lite) */ + { 0x9005, 0x0286, 0x1014, 0x9580, 0, 0, 46 }, /* IBM 8k/8k-l8 (Aurora) */ + { 0x9005, 0x0286, 0x1014, 0x9540, 0, 0, 47 }, /* IBM 8k/8k-l4 (Aurora Lite) */ + { 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 48 }, /* ASR-4000 (BlackBird) */ + { 0x9005, 0x0285, 0x9005, 0x0299, 0, 0, 49 }, /* ASR-4800SAS (Marauder-X) */ + { 0x9005, 0x0285, 0x9005, 0x029a, 0, 0, 50 }, /* ASR-4805SAS (Marauder-E) */ + { 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 51 }, /* ASR-3800 (Hurricane44) */ + + { 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 52 }, /* Perc 320/DC*/ + { 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 53 }, /* Adaptec 5400S (Mustang)*/ + { 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 54 }, /* Adaptec 5400S (Mustang)*/ + { 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 55 }, /* Dell PERC2/QC */ + { 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 56 }, /* HP NetRAID-4M */ + + { 0x9005, 0x0285, 0x1028, PCI_ANY_ID, 0, 0, 57 }, /* Dell Catchall */ + { 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 58 }, /* Legend Catchall */ + { 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 59 }, /* Adaptec Catch All */ + { 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 60 }, /* Adaptec Rocket Catch All */ { 0,} }; MODULE_DEVICE_TABLE(pci, aac_pci_tbl); @@ -131,68 +167,72 @@ MODULE_DEVICE_TABLE(pci, aac_pci_tbl); * for the card. At that time we can remove the channels from here */ static struct aac_driver_ident aac_drivers[] = { - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 2/Si */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Si */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Si */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */ - { aac_rx_init, "aacraid", "ADAPTEC ", "catapult ", 2, AAC_QUIRK_31BIT }, /* catapult*/ - { aac_rx_init, "aacraid", "ADAPTEC ", "tomcat ", 2, AAC_QUIRK_31BIT }, /* tomcat*/ - { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2120S ", 1, AAC_QUIRK_31BIT }, /* Adaptec 2120S (Crusader)*/ - { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT }, /* Adaptec 2200S (Vulcan)*/ - { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT }, /* Adaptec 2200S (Vulcan-2m)*/ - { aac_rx_init, "aacraid", "Legend ", "Legend S220 ", 1, AAC_QUIRK_31BIT }, /* Legend S220*/ - { aac_rx_init, "aacraid", "Legend ", "Legend S230 ", 2, AAC_QUIRK_31BIT }, /* Legend S230*/ - - { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 3230S ", 2 }, /* Adaptec 3230S (Harrier)*/ - { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 3240S ", 2 }, /* Adaptec 3240S (Tornado)*/ - { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020ZCR ", 2 }, /* ASR-2020 ZCR PCI-X U320 */ - { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2025ZCR ", 2 }, /* ASR-2025 ZCR DIMM U320 */ - { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 2 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II)*/ - - { aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2, AAC_QUIRK_31BIT }, /* Perc 320/DC*/ - { aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4 }, /* Adaptec 5400S (Mustang)*/ - { aac_sa_init, "aacraid", "ADAPTEC ", "AAC-364 ", 4 }, /* Adaptec 5400S (Mustang)*/ - { aac_sa_init, "percraid", "DELL ", "PERCRAID ", 4, AAC_QUIRK_31BIT }, /* Dell PERC2 "Quad Channel" */ - { aac_sa_init, "hpnraid", "HP ", "NetRAID ", 4 }, /* HP NetRAID-4M */ - - { aac_rx_init, "aacraid", "DELL ", "CERC SR2 ", 1 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */ - { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2810SA SATA ", 1 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ - { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-21610SA SATA", 1 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ - { aac_rx_init, "aacraid", "ADAPTEC ", "SO-DIMM SATA ZCR", 1 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */ - { aac_rx_init, "aacraid", "ADAPTEC ", "SATA 6Channel ", 1 }, /* SATA 6Ch (Bearcat) */ - - { aac_rkt_init,"aacraid", "ADAPTEC ", "ASR-2230S PCI-X ", 2 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */ - { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020SA ", 1 }, /* ASR-2020SA (ZCR PCI-X SATA) */ - { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2025SA ", 1 }, /* ASR-2025SA (ZCR DIMM SATA) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* PERC 2/Si (Iguana/PERC2Si) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* PERC 3/Di (Opal/PERC3Di) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* PERC 3/Si (SlimFast/PERC3Si */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* PERC 3/Di (Iguana FlipChip/PERC3DiF */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* PERC 3/Di (Viper/PERC3DiV) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* PERC 3/Di (Lexus/PERC3DiL) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 1, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* PERC 3/Di (Jaguar/PERC3DiJ) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* PERC 3/Di (Dagger/PERC3DiD) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* PERC 3/Di (Boxster/PERC3DiB) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "catapult ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* catapult */ + { aac_rx_init, "aacraid", "ADAPTEC ", "tomcat ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* tomcat */ + { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2120S ", 1, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec 2120S (Crusader) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec 2200S (Vulcan) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec 2200S (Vulcan-2m) */ + { aac_rx_init, "aacraid", "Legend ", "Legend S220 ", 1, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Legend S220 (Legend Crusader) */ + { aac_rx_init, "aacraid", "Legend ", "Legend S230 ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Legend S230 (Legend Vulcan) */ + + { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 3230S ", 2 }, /* Adaptec 3230S (Harrier) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 3240S ", 2 }, /* Adaptec 3240S (Tornado) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020ZCR ", 2 }, /* ASR-2020ZCR SCSI PCI-X ZCR (Skyhawk) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2025ZCR ", 2 }, /* ASR-2025ZCR SCSI SO-DIMM PCI-X ZCR (Terminator) */ + { aac_rkt_init, "aacraid", "ADAPTEC ", "ASR-2230S PCI-X ", 2 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */ + { aac_rkt_init, "aacraid", "ADAPTEC ", "ASR-2130S PCI-X ", 1 }, /* ASR-2130S (Lancer) */ + { aac_rkt_init, "aacraid", "ADAPTEC ", "AAR-2820SA ", 1 }, /* AAR-2820SA (Intruder) */ + { aac_rkt_init, "aacraid", "ADAPTEC ", "AAR-2620SA ", 1 }, /* AAR-2620SA (Intruder) */ + { aac_rkt_init, "aacraid", "ADAPTEC ", "AAR-2420SA ", 1 }, /* AAR-2420SA (Intruder) */ + { aac_rkt_init, "aacraid", "ICP ", "ICP9024RO ", 2 }, /* ICP9024RO (Lancer) */ + { aac_rkt_init, "aacraid", "ICP ", "ICP9014RO ", 1 }, /* ICP9014RO (Lancer) */ + { aac_rkt_init, "aacraid", "ICP ", "ICP9047MA ", 1 }, /* ICP9047MA (Lancer) */ + { aac_rkt_init, "aacraid", "ICP ", "ICP9087MA ", 1 }, /* ICP9087MA (Lancer) */ + { aac_rkt_init, "aacraid", "ICP ", "ICP5445AU ", 1 }, /* ICP5445AU (Hurricane44) */ + { aac_rx_init, "aacraid", "ICP ", "ICP9085LI ", 1 }, /* ICP9085LI (Marauder-X) */ + { aac_rx_init, "aacraid", "ICP ", "ICP5085BR ", 1 }, /* ICP5085BR (Marauder-E) */ + { aac_rkt_init, "aacraid", "ICP ", "ICP9067MA ", 1 }, /* ICP9067MA (Intruder-6) */ + { NULL , "aacraid", "ADAPTEC ", "Themisto ", 0, AAC_QUIRK_SLAVE }, /* Jupiter Platform */ + { aac_rkt_init, "aacraid", "ADAPTEC ", "Callisto ", 2, AAC_QUIRK_MASTER }, /* Jupiter Platform */ + { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020SA ", 1 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2025SA ", 1 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 1, AAC_QUIRK_17SG }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */ + { aac_rx_init, "aacraid", "DELL ", "CERC SR2 ", 1, AAC_QUIRK_17SG }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2810SA SATA ", 1, AAC_QUIRK_17SG }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-21610SA SATA", 1, AAC_QUIRK_17SG }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2026ZCR ", 1 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2610SA ", 1 }, /* SATA 6Ch (Bearcat) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2240S ", 1 }, /* ASR-2240S (SabreExpress) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4005 ", 1 }, /* ASR-4005 */ + { aac_rx_init, "ServeRAID","IBM ", "ServeRAID 8i ", 1 }, /* IBM 8i (AvonPark) */ + { aac_rkt_init, "ServeRAID","IBM ", "ServeRAID 8k-l8 ", 1 }, /* IBM 8k/8k-l8 (Aurora) */ + { aac_rkt_init, "ServeRAID","IBM ", "ServeRAID 8k-l4 ", 1 }, /* IBM 8k/8k-l4 (Aurora Lite) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4000 ", 1 }, /* ASR-4000 (BlackBird & AvonPark) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4800SAS ", 1 }, /* ASR-4800SAS (Marauder-X) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4805SAS ", 1 }, /* ASR-4805SAS (Marauder-E) */ + { aac_rkt_init, "aacraid", "ADAPTEC ", "ASR-3800 ", 1 }, /* ASR-3800 (Hurricane44) */ + + { aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/ + { aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/ + { aac_sa_init, "aacraid", "ADAPTEC ", "AAC-364 ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/ + { aac_sa_init, "percraid", "DELL ", "PERCRAID ", 4, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Dell PERC2/QC */ + { aac_sa_init, "hpnraid", "HP ", "NetRAID ", 4, AAC_QUIRK_34SG }, /* HP NetRAID-4M */ + + { aac_rx_init, "aacraid", "DELL ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Dell Catchall */ + { aac_rx_init, "aacraid", "Legend ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Legend Catchall */ + { aac_rx_init, "aacraid", "ADAPTEC ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec Catch All */ + { aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec Rocket Catch All */ }; -#ifdef CONFIG_COMPAT -/* - * Promote 32 bit apps that call get_next_adapter_fib_ioctl to 64 bit version - */ -static int aac_get_next_adapter_fib_ioctl(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *file) -{ - struct fib_ioctl __user *f; - - f = compat_alloc_user_space(sizeof(*f)); - if (!access_ok(VERIFY_WRITE, f, sizeof(*f))) - return -EFAULT; - - clear_user(f, sizeof(*f)); - if (copy_in_user(f, (void __user *)arg, sizeof(struct fib_ioctl) - sizeof(u32))) - return -EFAULT; - - return sys_ioctl(fd, cmd, (unsigned long)f); -} -#endif - - /** * aac_queuecommand - queue a SCSI command * @cmd: SCSI command to queue @@ -206,6 +246,7 @@ static int aac_get_next_adapter_fib_ioctl(unsigned int fd, unsigned int cmd, static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { cmd->scsi_done = done; + cmd->SCp.phase = AAC_OWNER_LOWLEVEL; return (aac_scsi_cmd(cmd) ? FAILED : 0); } @@ -216,7 +257,7 @@ static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd * Returns a static string describing the device in question */ -const char *aac_info(struct Scsi_Host *shost) +static const char *aac_info(struct Scsi_Host *shost) { struct aac_dev *dev = (struct aac_dev *)shost->hostdata; return aac_drivers[dev->cardtype].name; @@ -289,7 +330,9 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev, * translations ( 64/32, 128/32, 255/63 ). */ buf = scsi_bios_ptable(bdev); - if(*(unsigned short *)(buf + 0x40) == cpu_to_le16(0xaa55)) { + if (!buf) + return 0; + if(*(__le16 *)(buf + 0x40) == cpu_to_le16(0xaa55)) { struct partition *first = (struct partition * )buf; struct partition *entry = first; int saved_cylinders = param->cylinders; @@ -338,7 +381,7 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev, } /** - * aac_queuedepth - compute queue depths + * aac_slave_configure - compute queue depths * @sdev: SCSI device we are considering * * Selects queue depths for each target device based on the host adapter's @@ -348,10 +391,46 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev, static int aac_slave_configure(struct scsi_device *sdev) { - if (sdev->tagged_supported) - scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, 128); - else + if (sdev_channel(sdev) == CONTAINER_CHANNEL) { + sdev->skip_ms_page_8 = 1; + sdev->skip_ms_page_3f = 1; + } + if ((sdev->type == TYPE_DISK) && + !expose_physicals && + (sdev_channel(sdev) != CONTAINER_CHANNEL)) { + struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata; + if (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2)) + sdev->no_uld_attach = 1; + } + if (sdev->tagged_supported && (sdev->type == TYPE_DISK) && + (sdev_channel(sdev) == CONTAINER_CHANNEL)) { + struct scsi_device * dev; + struct Scsi_Host *host = sdev->host; + unsigned num_lsu = 0; + unsigned num_one = 0; + unsigned depth; + + __shost_for_each_device(dev, host) { + if (dev->tagged_supported && (dev->type == TYPE_DISK) && + (sdev_channel(dev) == CONTAINER_CHANNEL)) + ++num_lsu; + else + ++num_one; + } + if (num_lsu == 0) + ++num_lsu; + depth = (host->can_queue - num_one) / num_lsu; + if (depth > 256) + depth = 256; + else if (depth < 2) + depth = 2; + scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, depth); + if (!(((struct aac_dev *)host->hostdata)->adapter_info.options & + AAC_OPT_NEW_COMM)) + blk_queue_max_segment_size(sdev->request_queue, 65536); + } else scsi_adjust_queue_depth(sdev, 0, 1); + return 0; } @@ -361,14 +440,6 @@ static int aac_ioctl(struct scsi_device *sdev, int cmd, void __user * arg) return aac_do_ioctl(dev, cmd, arg); } -/* - * XXX: does aac really need no error handling?? - */ -static int aac_eh_abort(struct scsi_cmnd *cmd) -{ - return FAILED; -} - /* * aac_eh_reset - Reset command handling * @scsi_cmd: SCSI command block causing the reset @@ -385,39 +456,38 @@ static int aac_eh_reset(struct scsi_cmnd* cmd) printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", AAC_DRIVERNAME); - - aac = (struct aac_dev *)host->hostdata; - if (aac_adapter_check_health(aac)) { - printk(KERN_ERR "%s: Host adapter appears dead\n", - AAC_DRIVERNAME); - return -ENODEV; - } + + if ((count = aac_check_health(aac))) + return count; /* * Wait for all commands to complete to this specific * target (block maximum 60 seconds). */ for (count = 60; count; --count) { - int active = 0; + int active = aac->in_reset; + + if (active == 0) __shost_for_each_device(dev, host) { spin_lock_irqsave(&dev->list_lock, flags); list_for_each_entry(command, &dev->cmd_list, list) { - if (command->serial_number) { + if ((command != cmd) && + (command->SCp.phase == AAC_OWNER_FIRMWARE)) { active++; break; } } spin_unlock_irqrestore(&dev->list_lock, flags); + if (active) + break; - /* - * We can exit If all the commands are complete - */ - if (active == 0) - return SUCCESS; } - spin_unlock_irq(host->host_lock); - scsi_sleep(HZ); - spin_lock_irq(host->host_lock); + /* + * We can exit If all the commands are complete + */ + if (active == 0) + return SUCCESS; + ssleep(1); } printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME); return -ETIMEDOUT; @@ -437,12 +507,19 @@ static int aac_eh_reset(struct scsi_cmnd* cmd) static int aac_cfg_open(struct inode *inode, struct file *file) { - unsigned minor = iminor(inode); + struct aac_dev *aac; + unsigned minor_number = iminor(inode); + int err = -ENODEV; + + list_for_each_entry(aac, &aac_devices, entry) { + if (aac->id == minor_number) { + file->private_data = aac; + err = 0; + break; + } + } - if (minor >= aac_count) - return -ENODEV; - file->private_data = aac_devices[minor]; - return 0; + return err; } /** @@ -465,25 +542,257 @@ static int aac_cfg_ioctl(struct inode *inode, struct file *file, return aac_do_ioctl(file->private_data, cmd, (void __user *)arg); } +#ifdef CONFIG_COMPAT +static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long arg) +{ + long ret; + lock_kernel(); + switch (cmd) { + case FSACTL_MINIPORT_REV_CHECK: + case FSACTL_SENDFIB: + case FSACTL_OPEN_GET_ADAPTER_FIB: + case FSACTL_CLOSE_GET_ADAPTER_FIB: + case FSACTL_SEND_RAW_SRB: + case FSACTL_GET_PCI_INFO: + case FSACTL_QUERY_DISK: + case FSACTL_DELETE_DISK: + case FSACTL_FORCE_DELETE_DISK: + case FSACTL_GET_CONTAINERS: + case FSACTL_SEND_LARGE_FIB: + ret = aac_do_ioctl(dev, cmd, (void __user *)arg); + break; + + case FSACTL_GET_NEXT_ADAPTER_FIB: { + struct fib_ioctl __user *f; + + f = compat_alloc_user_space(sizeof(*f)); + ret = 0; + if (clear_user(f, sizeof(*f))) + ret = -EFAULT; + if (copy_in_user(f, (void __user *)arg, sizeof(struct fib_ioctl) - sizeof(u32))) + ret = -EFAULT; + if (!ret) + ret = aac_do_ioctl(dev, cmd, f); + break; + } + + default: + ret = -ENOIOCTLCMD; + break; + } + unlock_kernel(); + return ret; +} + +static int aac_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) +{ + struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata; + return aac_compat_do_ioctl(dev, cmd, (unsigned long)arg); +} + +static long aac_compat_cfg_ioctl(struct file *file, unsigned cmd, unsigned long arg) +{ + return aac_compat_do_ioctl((struct aac_dev *)file->private_data, cmd, arg); +} +#endif + +static ssize_t aac_show_model(struct class_device *class_dev, + char *buf) +{ + struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; + int len; + + if (dev->supplement_adapter_info.AdapterTypeText[0]) { + char * cp = dev->supplement_adapter_info.AdapterTypeText; + while (*cp && *cp != ' ') + ++cp; + while (*cp == ' ') + ++cp; + len = snprintf(buf, PAGE_SIZE, "%s\n", cp); + } else + len = snprintf(buf, PAGE_SIZE, "%s\n", + aac_drivers[dev->cardtype].model); + return len; +} + +static ssize_t aac_show_vendor(struct class_device *class_dev, + char *buf) +{ + struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; + int len; + + if (dev->supplement_adapter_info.AdapterTypeText[0]) { + char * cp = dev->supplement_adapter_info.AdapterTypeText; + while (*cp && *cp != ' ') + ++cp; + len = snprintf(buf, PAGE_SIZE, "%.*s\n", + (int)(cp - (char *)dev->supplement_adapter_info.AdapterTypeText), + dev->supplement_adapter_info.AdapterTypeText); + } else + len = snprintf(buf, PAGE_SIZE, "%s\n", + aac_drivers[dev->cardtype].vname); + return len; +} + +static ssize_t aac_show_kernel_version(struct class_device *class_dev, + char *buf) +{ + struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; + int len, tmp; + + tmp = le32_to_cpu(dev->adapter_info.kernelrev); + len = snprintf(buf, PAGE_SIZE, "%d.%d-%d[%d]\n", + tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff, + le32_to_cpu(dev->adapter_info.kernelbuild)); + return len; +} + +static ssize_t aac_show_monitor_version(struct class_device *class_dev, + char *buf) +{ + struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; + int len, tmp; + + tmp = le32_to_cpu(dev->adapter_info.monitorrev); + len = snprintf(buf, PAGE_SIZE, "%d.%d-%d[%d]\n", + tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff, + le32_to_cpu(dev->adapter_info.monitorbuild)); + return len; +} + +static ssize_t aac_show_bios_version(struct class_device *class_dev, + char *buf) +{ + struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; + int len, tmp; + + tmp = le32_to_cpu(dev->adapter_info.biosrev); + len = snprintf(buf, PAGE_SIZE, "%d.%d-%d[%d]\n", + tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff, + le32_to_cpu(dev->adapter_info.biosbuild)); + return len; +} + +static ssize_t aac_show_serial_number(struct class_device *class_dev, + char *buf) +{ + struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; + int len = 0; + + if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0) + len = snprintf(buf, PAGE_SIZE, "%x\n", + le32_to_cpu(dev->adapter_info.serial[0])); + return len; +} + +static ssize_t aac_show_max_channel(struct class_device *class_dev, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", + class_to_shost(class_dev)->max_channel); +} + +static ssize_t aac_show_max_id(struct class_device *class_dev, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", + class_to_shost(class_dev)->max_id); +} + + +static struct class_device_attribute aac_model = { + .attr = { + .name = "model", + .mode = S_IRUGO, + }, + .show = aac_show_model, +}; +static struct class_device_attribute aac_vendor = { + .attr = { + .name = "vendor", + .mode = S_IRUGO, + }, + .show = aac_show_vendor, +}; +static struct class_device_attribute aac_kernel_version = { + .attr = { + .name = "hba_kernel_version", + .mode = S_IRUGO, + }, + .show = aac_show_kernel_version, +}; +static struct class_device_attribute aac_monitor_version = { + .attr = { + .name = "hba_monitor_version", + .mode = S_IRUGO, + }, + .show = aac_show_monitor_version, +}; +static struct class_device_attribute aac_bios_version = { + .attr = { + .name = "hba_bios_version", + .mode = S_IRUGO, + }, + .show = aac_show_bios_version, +}; +static struct class_device_attribute aac_serial_number = { + .attr = { + .name = "serial_number", + .mode = S_IRUGO, + }, + .show = aac_show_serial_number, +}; +static struct class_device_attribute aac_max_channel = { + .attr = { + .name = "max_channel", + .mode = S_IRUGO, + }, + .show = aac_show_max_channel, +}; +static struct class_device_attribute aac_max_id = { + .attr = { + .name = "max_id", + .mode = S_IRUGO, + }, + .show = aac_show_max_id, +}; + +static struct class_device_attribute *aac_attrs[] = { + &aac_model, + &aac_vendor, + &aac_kernel_version, + &aac_monitor_version, + &aac_bios_version, + &aac_serial_number, + &aac_max_channel, + &aac_max_id, + NULL +}; + + static struct file_operations aac_cfg_fops = { .owner = THIS_MODULE, .ioctl = aac_cfg_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = aac_compat_cfg_ioctl, +#endif .open = aac_cfg_open, }; static struct scsi_host_template aac_driver_template = { .module = THIS_MODULE, .name = "AAC", - .proc_name = "aacraid", + .proc_name = AAC_DRIVERNAME, .info = aac_info, .ioctl = aac_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = aac_compat_ioctl, +#endif .queuecommand = aac_queuecommand, .bios_param = aac_biosparm, + .shost_attrs = aac_attrs, .slave_configure = aac_slave_configure, - .eh_abort_handler = aac_eh_abort, .eh_host_reset_handler = aac_eh_reset, .can_queue = AAC_NUM_IO_FIB, - .this_id = 16, + .this_id = MAXIMUM_NUM_CONTAINERS, .sg_tablesize = 16, .max_sectors = 128, #if (AAC_NUM_IO_FIB > 256) @@ -492,6 +801,7 @@ static struct scsi_host_template aac_driver_template = { .cmd_per_lun = AAC_NUM_IO_FIB, #endif .use_clustering = ENABLE_CLUSTERING, + .emulated = 1, }; @@ -500,38 +810,45 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, { unsigned index = id->driver_data; struct Scsi_Host *shost; - struct fsa_scsi_hba *fsa_dev_ptr; struct aac_dev *aac; - int container; + struct list_head *insert = &aac_devices; int error = -ENODEV; + int unique_id = 0; - if (pci_enable_device(pdev)) - goto out; + list_for_each_entry(aac, &aac_devices, entry) { + if (aac->id > unique_id) + break; + insert = &aac->entry; + unique_id++; + } - if (pci_set_dma_mask(pdev, 0xFFFFFFFFULL) || - pci_set_consistent_dma_mask(pdev, 0xFFFFFFFFULL)) + error = pci_enable_device(pdev); + if (error) goto out; + error = -ENODEV; + + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) || + pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) + goto out_disable_pdev; /* * If the quirk31 bit is set, the adapter needs adapter * to driver communication memory to be allocated below 2gig */ if (aac_drivers[index].quirks & AAC_QUIRK_31BIT) - if (pci_set_dma_mask(pdev, 0x7FFFFFFFULL) || - pci_set_consistent_dma_mask(pdev, 0x7FFFFFFFULL)) - goto out; + if (pci_set_dma_mask(pdev, DMA_31BIT_MASK) || + pci_set_consistent_dma_mask(pdev, DMA_31BIT_MASK)) + goto out_disable_pdev; pci_set_master(pdev); - /* Increment the host adapter count */ - aac_count++; - shost = scsi_host_alloc(&aac_driver_template, sizeof(struct aac_dev)); if (!shost) goto out_disable_pdev; shost->irq = pdev->irq; shost->base = pci_resource_start(pdev, 0); - shost->unique_id = aac_count - 1; + shost->unique_id = unique_id; + shost->max_cmd_len = 16; aac = (struct aac_dev *)shost->hostdata; aac->scsi_host_ptr = shost; @@ -539,19 +856,29 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, aac->name = aac_driver_template.name; aac->id = shost->unique_id; aac->cardtype = index; + INIT_LIST_HEAD(&aac->entry); - aac->fibs = kmalloc(sizeof(struct fib) * AAC_NUM_FIB, GFP_KERNEL); + aac->fibs = kmalloc(sizeof(struct fib) * (shost->can_queue + AAC_NUM_MGT_FIB), GFP_KERNEL); if (!aac->fibs) goto out_free_host; spin_lock_init(&aac->fib_lock); - /* Initialize the ordinal number of the device to -1 */ - fsa_dev_ptr = &aac->fsa_dev; - for (container = 0; container < MAXIMUM_NUM_CONTAINERS; container++) - fsa_dev_ptr->devname[container][0] = '\0'; - + /* + * Map in the registers from the adapter. + */ + aac->base_size = AAC_MIN_FOOTPRINT_SIZE; if ((*aac_drivers[index].init)(aac)) - goto out_free_fibs; + goto out_unmap; + + /* + * Start any kernel threads needed + */ + aac->thread = kthread_run(aac_command_thread, aac, AAC_DRIVERNAME); + if (IS_ERR(aac->thread)) { + printk(KERN_ERR "aacraid: Unable to create command thread.\n"); + error = PTR_ERR(aac->thread); + goto out_deinit; + } /* * If we had set a smaller DMA mask earlier, set it to 4gig @@ -559,61 +886,103 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, * address space. */ if (aac_drivers[index].quirks & AAC_QUIRK_31BIT) - if (pci_set_dma_mask(pdev, 0xFFFFFFFFULL)) - goto out_free_fibs; + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) + goto out_deinit; + + aac->maximum_num_channels = aac_drivers[index].channels; + error = aac_get_adapter_info(aac); + if (error < 0) + goto out_deinit; - aac_get_adapter_info(aac); + /* + * Lets override negotiations and drop the maximum SG limit to 34 + */ + if ((aac_drivers[index].quirks & AAC_QUIRK_34SG) && + (aac->scsi_host_ptr->sg_tablesize > 34)) { + aac->scsi_host_ptr->sg_tablesize = 34; + aac->scsi_host_ptr->max_sectors + = (aac->scsi_host_ptr->sg_tablesize * 8) + 112; + } + + if ((aac_drivers[index].quirks & AAC_QUIRK_17SG) && + (aac->scsi_host_ptr->sg_tablesize > 17)) { + aac->scsi_host_ptr->sg_tablesize = 17; + aac->scsi_host_ptr->max_sectors + = (aac->scsi_host_ptr->sg_tablesize * 8) + 112; + } /* + * Firware printf works only with older firmware. + */ + if (aac_drivers[index].quirks & AAC_QUIRK_34SG) + aac->printf_enabled = 1; + else + aac->printf_enabled = 0; + + /* * max channel will be the physical channels plus 1 virtual channel - * all containers are on the virtual channel 0 + * all containers are on the virtual channel 0 (CONTAINER_CHANNEL) * physical channels are address by their actual physical number+1 */ - if (aac->nondasd_support == 1) - shost->max_channel = aac_drivers[index].channels+1; + if ((aac->nondasd_support == 1) || expose_physicals) + shost->max_channel = aac->maximum_num_channels; else - shost->max_channel = 1; + shost->max_channel = 0; + aac_get_config_status(aac, 0); aac_get_containers(aac); - aac_devices[aac_count-1] = aac; + list_add(&aac->entry, insert); + + shost->max_id = aac->maximum_num_containers; + if (shost->max_id < aac->maximum_num_physicals) + shost->max_id = aac->maximum_num_physicals; + if (shost->max_id < MAXIMUM_NUM_CONTAINERS) + shost->max_id = MAXIMUM_NUM_CONTAINERS; + else + shost->this_id = shost->max_id; /* * dmb - we may need to move the setting of these parms somewhere else once * we get a fib that can report the actual numbers */ - shost->max_id = MAXIMUM_NUM_CONTAINERS; shost->max_lun = AAC_MAX_LUN; + pci_set_drvdata(pdev, shost); + error = scsi_add_host(shost, &pdev->dev); if (error) goto out_deinit; - - pci_set_drvdata(pdev, shost); scsi_scan_host(shost); return 0; out_deinit: - kill_proc(aac->thread_pid, SIGKILL, 0); - wait_for_completion(&aac->aif_completion); - + kthread_stop(aac->thread); aac_send_shutdown(aac); - fib_map_free(aac); + aac_adapter_disable_int(aac); + free_irq(pdev->irq, aac); + out_unmap: + aac_fib_map_free(aac); pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys); kfree(aac->queues); - free_irq(pdev->irq, aac); - iounmap((void * )aac->regs.sa); - out_free_fibs: + aac_adapter_ioremap(aac, 0); kfree(aac->fibs); + kfree(aac->fsa_dev); out_free_host: scsi_host_put(shost); out_disable_pdev: pci_disable_device(pdev); - aac_count--; out: return error; } +static void aac_shutdown(struct pci_dev *dev) +{ + struct Scsi_Host *shost = pci_get_drvdata(dev); + struct aac_dev *aac = (struct aac_dev *)shost->hostdata; + aac_send_shutdown(aac); +} + static void __devexit aac_remove_one(struct pci_dev *pdev) { struct Scsi_Host *shost = pci_get_drvdata(pdev); @@ -621,32 +990,28 @@ static void __devexit aac_remove_one(struct pci_dev *pdev) scsi_remove_host(shost); - kill_proc(aac->thread_pid, SIGKILL, 0); - wait_for_completion(&aac->aif_completion); + kthread_stop(aac->thread); aac_send_shutdown(aac); - fib_map_free(aac); + aac_adapter_disable_int(aac); + aac_fib_map_free(aac); pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys); kfree(aac->queues); free_irq(pdev->irq, aac); - iounmap((void * )aac->regs.sa); + aac_adapter_ioremap(aac, 0); kfree(aac->fibs); + kfree(aac->fsa_dev); + list_del(&aac->entry); scsi_host_put(shost); pci_disable_device(pdev); - - /* - * We don't decrement aac_count here because adapters can be unplugged - * in a different order than they were detected. If we're ever going - * to overflow MAXIMUM_NUM_ADAPTERS we'll have to consider using a - * bintmap of free aac_devices slots. - */ -#if 0 - aac_count--; -#endif + if (list_empty(&aac_devices)) { + unregister_chrdev(aac_cfg_major, "aac"); + aac_cfg_major = -1; + } } static struct pci_driver aac_pci_driver = { @@ -654,17 +1019,18 @@ static struct pci_driver aac_pci_driver = { .id_table = aac_pci_tbl, .probe = aac_probe_one, .remove = __devexit_p(aac_remove_one), + .shutdown = aac_shutdown, }; static int __init aac_init(void) { int error; - printk(KERN_INFO "Red Hat/Adaptec aacraid driver (%s %s)\n", - AAC_DRIVER_VERSION, AAC_DRIVER_BUILD_DATE); + printk(KERN_INFO "Adaptec %s driver (%s)\n", + AAC_DRIVERNAME, aac_driver_version); - error = pci_module_init(&aac_pci_driver); - if (error) + error = pci_register_driver(&aac_pci_driver); + if (error < 0) return error; aac_cfg_major = register_chrdev( 0, "aac", &aac_cfg_fops); @@ -672,40 +1038,14 @@ static int __init aac_init(void) printk(KERN_WARNING "aacraid: unable to register \"aac\" device.\n"); } -#ifdef CONFIG_COMPAT - register_ioctl32_conversion(FSACTL_MINIPORT_REV_CHECK, NULL); - register_ioctl32_conversion(FSACTL_SENDFIB, NULL); - register_ioctl32_conversion(FSACTL_OPEN_GET_ADAPTER_FIB, NULL); - register_ioctl32_conversion(FSACTL_GET_NEXT_ADAPTER_FIB, - aac_get_next_adapter_fib_ioctl); - register_ioctl32_conversion(FSACTL_CLOSE_GET_ADAPTER_FIB, NULL); - register_ioctl32_conversion(FSACTL_SEND_RAW_SRB, NULL); - register_ioctl32_conversion(FSACTL_GET_PCI_INFO, NULL); - register_ioctl32_conversion(FSACTL_QUERY_DISK, NULL); - register_ioctl32_conversion(FSACTL_DELETE_DISK, NULL); - register_ioctl32_conversion(FSACTL_FORCE_DELETE_DISK, NULL); - register_ioctl32_conversion(FSACTL_GET_CONTAINERS, NULL); -#endif return 0; } static void __exit aac_exit(void) { -#ifdef CONFIG_COMPAT - unregister_ioctl32_conversion(FSACTL_MINIPORT_REV_CHECK); - unregister_ioctl32_conversion(FSACTL_SENDFIB); - unregister_ioctl32_conversion(FSACTL_OPEN_GET_ADAPTER_FIB); - unregister_ioctl32_conversion(FSACTL_GET_NEXT_ADAPTER_FIB); - unregister_ioctl32_conversion(FSACTL_CLOSE_GET_ADAPTER_FIB); - unregister_ioctl32_conversion(FSACTL_SEND_RAW_SRB); - unregister_ioctl32_conversion(FSACTL_GET_PCI_INFO); - unregister_ioctl32_conversion(FSACTL_QUERY_DISK); - unregister_ioctl32_conversion(FSACTL_DELETE_DISK); - unregister_ioctl32_conversion(FSACTL_FORCE_DELETE_DISK); - unregister_ioctl32_conversion(FSACTL_GET_CONTAINERS); -#endif - unregister_chrdev(aac_cfg_major, "aac"); + if (aac_cfg_major > -1) + unregister_chrdev(aac_cfg_major, "aac"); pci_unregister_driver(&aac_pci_driver); }