This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / drivers / scsi / BusLogic.c
index 41b5197..06faeb2 100644 (file)
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
+#include "scsi.h"
 #include <scsi/scsi_host.h>
-#include <scsi/scsi_tcq.h>
 #include "BusLogic.h"
 #include "FlashPoint.c"
 
@@ -59,8 +56,6 @@
 #define FAILURE (-1)
 #endif
 
-static struct scsi_host_template Bus_Logic_template;
-
 /*
   BusLogic_DriverOptionsCount is a count of the number of BusLogic Driver
   Options specifications provided via the Linux Kernel Command Line or via
@@ -86,7 +81,7 @@ static struct BusLogic_DriverOptions BusLogic_DriverOptions[BusLogic_MaxHostAdap
 MODULE_LICENSE("GPL");
 #ifdef MODULE
 static char *BusLogic;
-module_param(BusLogic, charp, 0);
+MODULE_PARM(BusLogic, "s");
 #endif
 
 
@@ -105,7 +100,15 @@ static struct BusLogic_ProbeOptions BusLogic_ProbeOptions;
 
 static struct BusLogic_GlobalOptions BusLogic_GlobalOptions;
 
-static LIST_HEAD(BusLogic_host_list);
+
+/*
+  BusLogic_FirstRegisteredHostAdapter and BusLogic_LastRegisteredHostAdapter
+  are pointers to the first and last registered BusLogic Host Adapters.
+*/
+
+static struct BusLogic_HostAdapter *BusLogic_FirstRegisteredHostAdapter;
+static struct BusLogic_HostAdapter *BusLogic_LastRegisteredHostAdapter;
+
 
 /*
   BusLogic_ProbeInfoCount is the number of entries in BusLogic_ProbeInfoList.
@@ -155,6 +158,47 @@ static const char *BusLogic_DriverInfo(struct Scsi_Host *Host)
        return HostAdapter->FullModelName;
 }
 
+
+/*
+  BusLogic_RegisterHostAdapter adds Host Adapter to the list of registered
+  BusLogic Host Adapters.
+*/
+
+static void __init BusLogic_RegisterHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
+{
+       HostAdapter->Next = NULL;
+       if (BusLogic_FirstRegisteredHostAdapter == NULL) {
+               BusLogic_FirstRegisteredHostAdapter = HostAdapter;
+               BusLogic_LastRegisteredHostAdapter = HostAdapter;
+       } else {
+               BusLogic_LastRegisteredHostAdapter->Next = HostAdapter;
+               BusLogic_LastRegisteredHostAdapter = HostAdapter;
+       }
+}
+
+
+/*
+  BusLogic_UnregisterHostAdapter removes Host Adapter from the list of
+  registered BusLogic Host Adapters.
+*/
+
+static void BusLogic_UnregisterHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
+{
+       if (HostAdapter == BusLogic_FirstRegisteredHostAdapter) {
+               BusLogic_FirstRegisteredHostAdapter = BusLogic_FirstRegisteredHostAdapter->Next;
+               if (HostAdapter == BusLogic_LastRegisteredHostAdapter)
+                       BusLogic_LastRegisteredHostAdapter = NULL;
+       } else {
+               struct BusLogic_HostAdapter *PreviousHostAdapter = BusLogic_FirstRegisteredHostAdapter;
+               while (PreviousHostAdapter != NULL && PreviousHostAdapter->Next != HostAdapter)
+                       PreviousHostAdapter = PreviousHostAdapter->Next;
+               if (PreviousHostAdapter != NULL)
+                       PreviousHostAdapter->Next = HostAdapter->Next;
+       }
+       HostAdapter->Next = NULL;
+}
+
+
 /*
   BusLogic_InitializeCCBs initializes a group of Command Control Blocks (CCBs)
   for Host Adapter from the BlockSize bytes located at BlockPointer.  The newly
@@ -303,19 +347,12 @@ static struct BusLogic_CCB *BusLogic_AllocateCCB(struct BusLogic_HostAdapter
 static void BusLogic_DeallocateCCB(struct BusLogic_CCB *CCB)
 {
        struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter;
-       struct scsi_cmnd *cmd = CCB->Command;
-
-       if (cmd->use_sg != 0) {
-               pci_unmap_sg(HostAdapter->PCI_Device,
-                               (struct scatterlist *)cmd->request_buffer,
-                               cmd->use_sg, cmd->sc_data_direction);
-       } else if (cmd->request_bufflen != 0) {
-               pci_unmap_single(HostAdapter->PCI_Device, CCB->DataPointer,
-                               CCB->DataLength, cmd->sc_data_direction);
+       if (CCB->Command->use_sg != 0) {
+               pci_unmap_sg(HostAdapter->PCI_Device, (struct scatterlist *) CCB->Command->request_buffer, CCB->Command->use_sg, scsi_to_pci_dma_dir(CCB->Command->sc_data_direction));
+       } else if (CCB->Command->request_bufflen != 0) {
+               pci_unmap_single(HostAdapter->PCI_Device, CCB->DataPointer, CCB->DataLength, scsi_to_pci_dma_dir(CCB->Command->sc_data_direction));
        }
-       pci_unmap_single(HostAdapter->PCI_Device, CCB->SenseDataPointer,
-                       CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
-
+       pci_unmap_single(HostAdapter->PCI_Device, CCB->SenseDataPointer, CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
        CCB->Command = NULL;
        CCB->Status = BusLogic_CCB_Free;
        CCB->Next = HostAdapter->Free_CCBs;
@@ -2171,23 +2208,17 @@ static int BusLogic_SlaveConfigure(struct scsi_device *Device)
   registered.
 */
 
-static int __init BusLogic_init(void)
+static int __init BusLogic_DetectHostAdapter(struct scsi_host_template *HostTemplate)
 {
        int BusLogicHostAdapterCount = 0, DriverOptionsIndex = 0, ProbeIndex;
        struct BusLogic_HostAdapter *PrototypeHostAdapter;
-
-#ifdef MODULE
-       if (BusLogic)
-               BusLogic_Setup(BusLogic);
-#endif
-
        if (BusLogic_ProbeOptions.NoProbe)
-               return -ENODEV;
+               return 0;
        BusLogic_ProbeInfoList = (struct BusLogic_ProbeInfo *)
            kmalloc(BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo), GFP_ATOMIC);
        if (BusLogic_ProbeInfoList == NULL) {
                BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL);
-               return -ENOMEM;
+               return 0;
        }
        memset(BusLogic_ProbeInfoList, 0, BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo));
        PrototypeHostAdapter = (struct BusLogic_HostAdapter *)
@@ -2195,7 +2226,7 @@ static int __init BusLogic_init(void)
        if (PrototypeHostAdapter == NULL) {
                kfree(BusLogic_ProbeInfoList);
                BusLogic_Error("BusLogic: Unable to allocate Prototype " "Host Adapter\n", NULL);
-               return -ENOMEM;
+               return 0;
        }
        memset(PrototypeHostAdapter, 0, sizeof(struct BusLogic_HostAdapter));
 #ifdef MODULE
@@ -2258,7 +2289,7 @@ static int __init BusLogic_init(void)
                   Register the SCSI Host structure.
                 */
 
-               Host = scsi_host_alloc(&Bus_Logic_template, sizeof(struct BusLogic_HostAdapter));
+               Host = scsi_host_alloc(HostTemplate, sizeof(struct BusLogic_HostAdapter));
                if (Host == NULL) {
                        release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
                        continue;
@@ -2271,8 +2302,7 @@ static int __init BusLogic_init(void)
                   Add Host Adapter to the end of the list of registered BusLogic
                   Host Adapters.
                 */
-               list_add_tail(&HostAdapter->host_list, &BusLogic_host_list);
-
+               BusLogic_RegisterHostAdapter(HostAdapter);
                /*
                   Read the Host Adapter Configuration, Configure the Host Adapter,
                   Acquire the System Resources necessary to use the Host Adapter, then
@@ -2292,7 +2322,7 @@ static int __init BusLogic_init(void)
                                printk(KERN_WARNING "BusLogic: Release and re-register of " "port 0x%04lx failed \n", (unsigned long) HostAdapter->IO_Address);
                                BusLogic_DestroyCCBs(HostAdapter);
                                BusLogic_ReleaseResources(HostAdapter);
-                               list_del(&HostAdapter->host_list);
+                               BusLogic_UnregisterHostAdapter(HostAdapter);
                                scsi_host_put(Host);
                        } else {
                                BusLogic_InitializeHostStructure(HostAdapter, Host);
@@ -2311,14 +2341,14 @@ static int __init BusLogic_init(void)
                         */
                        BusLogic_DestroyCCBs(HostAdapter);
                        BusLogic_ReleaseResources(HostAdapter);
-                       list_del(&HostAdapter->host_list);
+                       BusLogic_UnregisterHostAdapter(HostAdapter);
                        scsi_host_put(Host);
                }
        }
        kfree(PrototypeHostAdapter);
        kfree(BusLogic_ProbeInfoList);
        BusLogic_ProbeInfoList = NULL;
-       return 0;
+       return BusLogicHostAdapterCount;
 }
 
 
@@ -2328,12 +2358,9 @@ static int __init BusLogic_init(void)
   unregisters the BusLogic Host Adapter.
 */
 
-static int __exit BusLogic_ReleaseHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
+static int __exit BusLogic_ReleaseHostAdapter(struct Scsi_Host *Host)
 {
-       struct Scsi_Host *Host = HostAdapter->SCSI_Host;
-
-       scsi_remove_host(Host);
-
+       struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Host->hostdata;
        /*
           FlashPoint Host Adapters must first be released by the FlashPoint
           SCCB Manager.
@@ -2353,9 +2380,7 @@ static int __exit BusLogic_ReleaseHostAdapter(struct BusLogic_HostAdapter *HostA
        /*
           Remove Host Adapter from the list of registered BusLogic Host Adapters.
         */
-       list_del(&HostAdapter->host_list);
-
-       scsi_host_put(Host);
+       BusLogic_UnregisterHostAdapter(HostAdapter);
        return 0;
 }
 
@@ -2631,7 +2656,7 @@ static irqreturn_t BusLogic_InterruptHandler(int IRQ_Channel, void *DeviceIdenti
        /*
           Acquire exclusive access to Host Adapter.
         */
-       spin_lock_irqsave(HostAdapter->SCSI_Host->host_lock, ProcessorFlags);
+       BusLogic_AcquireHostAdapterLockIH(HostAdapter, &ProcessorFlags);
        /*
           Handle Interrupts appropriately for each Host Adapter type.
         */
@@ -2699,7 +2724,7 @@ static irqreturn_t BusLogic_InterruptHandler(int IRQ_Channel, void *DeviceIdenti
        /*
           Release exclusive access to Host Adapter.
         */
-       spin_unlock_irqrestore(HostAdapter->SCSI_Host->host_lock, ProcessorFlags);
+       BusLogic_ReleaseHostAdapterLockIH(HostAdapter, &ProcessorFlags);
        return IRQ_HANDLED;
 }
 
@@ -2740,7 +2765,7 @@ static boolean BusLogic_WriteOutgoingMailbox(struct BusLogic_HostAdapter
 
 /* Error Handling (EH) support */
 
-static int BusLogic_host_reset(struct scsi_cmnd * SCpnt)
+static int BusLogic_host_reset(Scsi_Cmnd * SCpnt)
 {
        struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) SCpnt->device->host->hostdata;
 
@@ -2787,9 +2812,9 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRou
         */
        CCB = BusLogic_AllocateCCB(HostAdapter);
        if (CCB == NULL) {
-               spin_unlock_irq(HostAdapter->SCSI_Host->host_lock);
+               BusLogic_ReleaseHostAdapterLock(HostAdapter);
                BusLogic_Delay(1);
-               spin_lock_irq(HostAdapter->SCSI_Host->host_lock);
+               BusLogic_AcquireHostAdapterLock(HostAdapter);
                CCB = BusLogic_AllocateCCB(HostAdapter);
                if (CCB == NULL) {
                        Command->result = DID_ERROR << 16;
@@ -2803,15 +2828,12 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRou
        if (SegmentCount == 0 && BufferLength != 0) {
                CCB->Opcode = BusLogic_InitiatorCCB;
                CCB->DataLength = BufferLength;
-               CCB->DataPointer = pci_map_single(HostAdapter->PCI_Device,
-                               BufferPointer, BufferLength,
-                               Command->sc_data_direction);
+               CCB->DataPointer = pci_map_single(HostAdapter->PCI_Device, BufferPointer, BufferLength, scsi_to_pci_dma_dir(Command->sc_data_direction));
        } else if (SegmentCount != 0) {
                struct scatterlist *ScatterList = (struct scatterlist *) BufferPointer;
                int Segment, Count;
 
-               Count = pci_map_sg(HostAdapter->PCI_Device, ScatterList, SegmentCount,
-                               Command->sc_data_direction);
+               Count = pci_map_sg(HostAdapter->PCI_Device, ScatterList, SegmentCount, scsi_to_pci_dma_dir(Command->sc_data_direction));
                CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather;
                CCB->DataLength = Count * sizeof(struct BusLogic_ScatterGatherSegment);
                if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
@@ -2916,10 +2938,10 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRou
                   error as a Host Adapter Hard Reset should be initiated soon.
                 */
                if (!BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxStartCommand, CCB)) {
-                       spin_unlock_irq(HostAdapter->SCSI_Host->host_lock);
+                       BusLogic_ReleaseHostAdapterLock(HostAdapter);
                        BusLogic_Warning("Unable to write Outgoing Mailbox - " "Pausing for 1 second\n", HostAdapter);
                        BusLogic_Delay(1);
-                       spin_lock_irq(HostAdapter->SCSI_Host->host_lock);
+                       BusLogic_AcquireHostAdapterLock(HostAdapter);
                        if (!BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxStartCommand, CCB)) {
                                BusLogic_Warning("Still unable to write Outgoing Mailbox - " "Host Adapter Dead?\n", HostAdapter);
                                BusLogic_DeallocateCCB(CCB);
@@ -3057,9 +3079,9 @@ static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, b
         */
 
        if (HardReset) {
-               spin_unlock_irq(HostAdapter->SCSI_Host->host_lock);
+               BusLogic_ReleaseHostAdapterLock(HostAdapter);
                BusLogic_Delay(HostAdapter->BusSettleTime);
-               spin_lock_irq(HostAdapter->SCSI_Host->host_lock);
+               BusLogic_AcquireHostAdapterLock(HostAdapter);
        }
 
        for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
@@ -3159,11 +3181,17 @@ static int BusLogic_BIOSDiskParameters(struct scsi_device *sdev, struct block_de
 
 static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *shost, char *ProcBuffer, char **StartPointer, off_t Offset, int BytesAvailable, int WriteFlag)
 {
-       struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) shost->hostdata;
+       struct BusLogic_HostAdapter *HostAdapter;
        struct BusLogic_TargetStatistics *TargetStatistics;
        int TargetID, Length;
        char *Buffer;
-
+       for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; HostAdapter != NULL; HostAdapter = HostAdapter->Next)
+               if (HostAdapter->HostNumber == shost->host_no)
+                       break;
+       if (HostAdapter == NULL) {
+               BusLogic_Error("Cannot find Host Adapter for SCSI Host %d\n", NULL, shost->host_no);
+               return 0;
+       }
        TargetStatistics = HostAdapter->TargetStatistics;
        if (WriteFlag) {
                HostAdapter->ExternalHostAdapterResets = 0;
@@ -3519,7 +3547,7 @@ static int __init BusLogic_ParseDriverOptions(char *OptionsString)
   Get it all started
 */
 
-static struct scsi_host_template Bus_Logic_template = {
+static struct scsi_host_template driver_template = {
        .module = THIS_MODULE,
        .proc_name = "BusLogic",
        .proc_info = BusLogic_ProcDirectoryInfo,
@@ -3556,16 +3584,37 @@ static int __init BusLogic_Setup(char *str)
        return BusLogic_ParseDriverOptions(str);
 }
 
+/*
+ * Initialization function
+ */
+
+static int __init BusLogic_init(void)
+{
+
+#ifdef MODULE
+       if (BusLogic)
+               BusLogic_Setup(BusLogic);
+#endif
+
+       return BusLogic_DetectHostAdapter(&driver_template) ? 0 : -ENODEV;
+}
+
 /*
  * Exit function.  Deletes all hosts associated with this driver.
  */
 
 static void __exit BusLogic_exit(void)
 {
-       struct BusLogic_HostAdapter *ha, *next;
+       struct BusLogic_HostAdapter *HostAdapter;
+       for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; HostAdapter != NULL; HostAdapter = HostAdapter->Next) {
+               struct Scsi_Host *host = HostAdapter->SCSI_Host;
+               scsi_remove_host(host);
 
-       list_for_each_entry_safe(ha, next, &BusLogic_host_list, host_list)
-               BusLogic_ReleaseHostAdapter(ha);
+       }
+       for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; HostAdapter != NULL; HostAdapter = HostAdapter->Next) {
+               struct Scsi_Host *host = HostAdapter->SCSI_Host;
+               BusLogic_ReleaseHostAdapter(host);
+       }
 }
 
 __setup("BusLogic=", BusLogic_Setup);