Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[powerpc.git] / drivers / ieee1394 / sbp2.c
index f0763b7..f420660 100644 (file)
@@ -137,15 +137,15 @@ MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device (default = 1)"
 /*
  * SCSI inquiry hack for really badly behaved sbp2 devices. Turn this on
  * if your sbp2 device is not properly handling the SCSI inquiry command.
- * This hack makes the inquiry look more like a typical MS Windows
- * inquiry.
+ * This hack makes the inquiry look more like a typical MS Windows inquiry
+ * by enforcing 36 byte inquiry and avoiding access to mode_sense page 8.
  *
  * If force_inquiry_hack=1 is required for your device to work,
  * please submit the logged sbp2_firmware_revision value of this device to
  * the linux1394-devel mailing list.
  */
 static int force_inquiry_hack;
-module_param(force_inquiry_hack, int, 0444);
+module_param(force_inquiry_hack, int, 0644);
 MODULE_PARM_DESC(force_inquiry_hack, "Force SCSI inquiry hack (default = 0)");
 
 /*
@@ -214,6 +214,7 @@ static u32 global_outstanding_dmas = 0;
 #endif
 
 #define SBP2_ERR(fmt, args...)         HPSB_ERR("sbp2: "fmt, ## args)
+#define SBP2_DEBUG_ENTER()             SBP2_DEBUG("%s", __FUNCTION__)
 
 /*
  * Globals
@@ -264,18 +265,17 @@ static struct hpsb_protocol_driver sbp2_driver = {
        },
 };
 
-
-/* List of device firmware's that require a forced 36 byte inquiry.  */
+/*
+ * List of device firmwares that require the inquiry hack.
+ * Yields a few false positives but did not break other devices so far.
+ */
 static u32 sbp2_broken_inquiry_list[] = {
-       0x00002800,     /* Stefan Richter <richtest@bauwesen.tu-cottbus.de> */
+       0x00002800,     /* Stefan Richter <stefanr@s5r6.in-berlin.de> */
                        /* DViCO Momobay CX-1 */
        0x00000200      /* Andreas Plesch <plesch@fas.harvard.edu> */
                        /* QPS Fire DVDBurner */
 };
 
-#define NUM_BROKEN_INQUIRY_DEVS \
-       (sizeof(sbp2_broken_inquiry_list)/sizeof(*sbp2_broken_inquiry_list))
-
 /**************************************
  * General utility functions
  **************************************/
@@ -496,22 +496,17 @@ static struct sbp2_command_info *sbp2util_find_command_for_orb(
 /*
  * This function finds the sbp2_command for a given outstanding SCpnt.
  * Only looks at the inuse list.
+ * Must be called with scsi_id->sbp2_command_orb_lock held.
  */
-static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt)
+static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(
+               struct scsi_id_instance_data *scsi_id, void *SCpnt)
 {
        struct sbp2_command_info *command;
-       unsigned long flags;
 
-       spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
-       if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
-               list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) {
-                       if (command->Current_SCpnt == SCpnt) {
-                               spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
+       if (!list_empty(&scsi_id->sbp2_command_orb_inuse))
+               list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list)
+                       if (command->Current_SCpnt == SCpnt)
                                return command;
-                       }
-               }
-       }
-       spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
        return NULL;
 }
 
@@ -536,7 +531,7 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb(
                command->Current_SCpnt = Current_SCpnt;
                list_add_tail(&command->list, &scsi_id->sbp2_command_orb_inuse);
        } else {
-               SBP2_ERR("sbp2util_allocate_command_orb - No orbs available!");
+               SBP2_ERR("%s: no orbs available", __FUNCTION__);
        }
        spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
        return command;
@@ -550,7 +545,7 @@ static void sbp2util_free_command_dma(struct sbp2_command_info *command)
        struct hpsb_host *host;
 
        if (!scsi_id) {
-               printk(KERN_ERR "%s: scsi_id == NULL\n", __FUNCTION__);
+               SBP2_ERR("%s: scsi_id == NULL", __FUNCTION__);
                return;
        }
 
@@ -580,17 +575,15 @@ static void sbp2util_free_command_dma(struct sbp2_command_info *command)
 
 /*
  * This function moves a command to the completed orb list.
+ * Must be called with scsi_id->sbp2_command_orb_lock held.
  */
-static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id,
-                                           struct sbp2_command_info *command)
+static void sbp2util_mark_command_completed(
+               struct scsi_id_instance_data *scsi_id,
+               struct sbp2_command_info *command)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
        list_del(&command->list);
        sbp2util_free_command_dma(command);
        list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed);
-       spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 }
 
 /*
@@ -611,7 +604,7 @@ static int sbp2_probe(struct device *dev)
        struct unit_directory *ud;
        struct scsi_id_instance_data *scsi_id;
 
-       SBP2_DEBUG("sbp2_probe");
+       SBP2_DEBUG_ENTER();
 
        ud = container_of(dev, struct unit_directory, device);
 
@@ -636,16 +629,22 @@ static int sbp2_remove(struct device *dev)
        struct scsi_id_instance_data *scsi_id;
        struct scsi_device *sdev;
 
-       SBP2_DEBUG("sbp2_remove");
+       SBP2_DEBUG_ENTER();
 
        ud = container_of(dev, struct unit_directory, device);
        scsi_id = ud->device.driver_data;
        if (!scsi_id)
                return 0;
 
-       /* Trigger shutdown functions in scsi's highlevel. */
-       if (scsi_id->scsi_host)
+       if (scsi_id->scsi_host) {
+               /* Get rid of enqueued commands if there is no chance to
+                * send them. */
+               if (!sbp2util_node_is_available(scsi_id))
+                       sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT);
+               /* scsi_remove_device() will trigger shutdown functions of SCSI
+                * highlevel drivers which would deadlock if blocked. */
                scsi_unblock_requests(scsi_id->scsi_host);
+       }
        sdev = scsi_id->sdev;
        if (sdev) {
                scsi_id->sdev = NULL;
@@ -662,7 +661,7 @@ static int sbp2_update(struct unit_directory *ud)
 {
        struct scsi_id_instance_data *scsi_id = ud->device.driver_data;
 
-       SBP2_DEBUG("sbp2_update");
+       SBP2_DEBUG_ENTER();
 
        if (sbp2_reconnect_device(scsi_id)) {
 
@@ -710,7 +709,7 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
        struct Scsi_Host *scsi_host = NULL;
        struct scsi_id_instance_data *scsi_id = NULL;
 
-       SBP2_DEBUG("sbp2_alloc_device");
+       SBP2_DEBUG_ENTER();
 
        scsi_id = kzalloc(sizeof(*scsi_id), GFP_KERNEL);
        if (!scsi_id) {
@@ -742,23 +741,40 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
                hi->host = ud->ne->host;
                INIT_LIST_HEAD(&hi->scsi_ids);
 
-               /* Register our sbp2 status address space... */
-               hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, &sbp2_ops,
-                                       SBP2_STATUS_FIFO_ADDRESS,
-                                       SBP2_STATUS_FIFO_ADDRESS +
-                                       SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2_MAX_UDS_PER_NODE+1));
 #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
                /* Handle data movement if physical dma is not
-                * enabled/supportedon host controller */
-               hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, &sbp2_physdma_ops,
-                                       0x0ULL, 0xfffffffcULL);
+                * enabled or not supported on host controller */
+               if (!hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host,
+                                            &sbp2_physdma_ops,
+                                            0x0ULL, 0xfffffffcULL)) {
+                       SBP2_ERR("failed to register lower 4GB address range");
+                       goto failed_alloc;
+               }
 #endif
        }
 
+       /* Prevent unloading of the 1394 host */
+       if (!try_module_get(hi->host->driver->owner)) {
+               SBP2_ERR("failed to get a reference on 1394 host driver");
+               goto failed_alloc;
+       }
+
        scsi_id->hi = hi;
 
        list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids);
 
+       /* Register the status FIFO address range. We could use the same FIFO
+        * for targets at different nodes. However we need different FIFOs per
+        * target in order to support multi-unit devices. */
+       scsi_id->status_fifo_addr = hpsb_allocate_and_register_addrspace(
+                       &sbp2_highlevel, ud->ne->host, &sbp2_ops,
+                       sizeof(struct sbp2_status_block), sizeof(quadlet_t),
+                       ~0ULL, ~0ULL);
+       if (!scsi_id->status_fifo_addr) {
+               SBP2_ERR("failed to allocate status FIFO address range");
+               goto failed_alloc;
+       }
+
        /* Register our host with the SCSI stack. */
        scsi_host = scsi_host_alloc(&scsi_driver_template,
                                    sizeof(unsigned long));
@@ -804,7 +820,7 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
        struct sbp2scsi_host_info *hi = scsi_id->hi;
        int error;
 
-       SBP2_DEBUG("sbp2_start_device");
+       SBP2_DEBUG_ENTER();
 
        /* Login FIFO DMA */
        scsi_id->login_response =
@@ -856,56 +872,8 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
                pci_alloc_consistent(hi->host->pdev,
                                     sizeof(struct sbp2_login_orb),
                                     &scsi_id->login_orb_dma);
-       if (!scsi_id->login_orb) {
-alloc_fail:
-               if (scsi_id->query_logins_response) {
-                       pci_free_consistent(hi->host->pdev,
-                                           sizeof(struct sbp2_query_logins_response),
-                                           scsi_id->query_logins_response,
-                                           scsi_id->query_logins_response_dma);
-                       SBP2_DMA_FREE("query logins response DMA");
-               }
-
-               if (scsi_id->query_logins_orb) {
-                       pci_free_consistent(hi->host->pdev,
-                                           sizeof(struct sbp2_query_logins_orb),
-                                           scsi_id->query_logins_orb,
-                                           scsi_id->query_logins_orb_dma);
-                       SBP2_DMA_FREE("query logins ORB DMA");
-               }
-
-               if (scsi_id->logout_orb) {
-                       pci_free_consistent(hi->host->pdev,
-                                           sizeof(struct sbp2_logout_orb),
-                                           scsi_id->logout_orb,
-                                           scsi_id->logout_orb_dma);
-                       SBP2_DMA_FREE("logout ORB DMA");
-               }
-
-               if (scsi_id->reconnect_orb) {
-                       pci_free_consistent(hi->host->pdev,
-                                           sizeof(struct sbp2_reconnect_orb),
-                                           scsi_id->reconnect_orb,
-                                           scsi_id->reconnect_orb_dma);
-                       SBP2_DMA_FREE("reconnect ORB DMA");
-               }
-
-               if (scsi_id->login_response) {
-                       pci_free_consistent(hi->host->pdev,
-                                           sizeof(struct sbp2_login_response),
-                                           scsi_id->login_response,
-                                           scsi_id->login_response_dma);
-                       SBP2_DMA_FREE("login FIFO DMA");
-               }
-
-               list_del(&scsi_id->scsi_list);
-
-               kfree(scsi_id);
-
-               SBP2_ERR("Could not allocate memory for scsi_id");
-
-               return -ENOMEM;
-       }
+       if (!scsi_id->login_orb)
+               goto alloc_fail;
        SBP2_DMA_ALLOC("consistent DMA region for login ORB");
 
        SBP2_DEBUG("New SBP-2 device inserted, SCSI ID = %x", scsi_id->ud->id);
@@ -927,7 +895,6 @@ alloc_fail:
         * allows someone else to login instead. One second makes sense. */
        msleep_interruptible(1000);
        if (signal_pending(current)) {
-               SBP2_WARN("aborting sbp2_start_device due to event");
                sbp2_remove_device(scsi_id);
                return -EINTR;
        }
@@ -960,10 +927,17 @@ alloc_fail:
        error = scsi_add_device(scsi_id->scsi_host, 0, scsi_id->ud->id, 0);
        if (error) {
                SBP2_ERR("scsi_add_device failed");
+               sbp2_logout_device(scsi_id);
+               sbp2_remove_device(scsi_id);
                return error;
        }
 
        return 0;
+
+alloc_fail:
+       SBP2_ERR("Could not allocate memory for scsi_id");
+       sbp2_remove_device(scsi_id);
+       return -ENOMEM;
 }
 
 /*
@@ -973,7 +947,7 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
 {
        struct sbp2scsi_host_info *hi;
 
-       SBP2_DEBUG("sbp2_remove_device");
+       SBP2_DEBUG_ENTER();
 
        if (!scsi_id)
                return;
@@ -1038,8 +1012,15 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
                SBP2_DMA_FREE("single query logins data");
        }
 
+       if (scsi_id->status_fifo_addr)
+               hpsb_unregister_addrspace(&sbp2_highlevel, hi->host,
+                       scsi_id->status_fifo_addr);
+
        scsi_id->ud->device.driver_data = NULL;
 
+       if (hi)
+               module_put(hi->host->driver->owner);
+
        SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->ud->id);
 
        kfree(scsi_id);
@@ -1098,51 +1079,41 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
        int max_logins;
        int active_logins;
 
-       SBP2_DEBUG("sbp2_query_logins");
+       SBP2_DEBUG_ENTER();
 
        scsi_id->query_logins_orb->reserved1 = 0x0;
        scsi_id->query_logins_orb->reserved2 = 0x0;
 
        scsi_id->query_logins_orb->query_response_lo = scsi_id->query_logins_response_dma;
        scsi_id->query_logins_orb->query_response_hi = ORB_SET_NODE_ID(hi->host->node_id);
-       SBP2_DEBUG("sbp2_query_logins: query_response_hi/lo initialized");
 
        scsi_id->query_logins_orb->lun_misc = ORB_SET_FUNCTION(SBP2_QUERY_LOGINS_REQUEST);
        scsi_id->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1);
        scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun);
-       SBP2_DEBUG("sbp2_query_logins: lun_misc initialized");
 
        scsi_id->query_logins_orb->reserved_resp_length =
                ORB_SET_QUERY_LOGINS_RESP_LENGTH(sizeof(struct sbp2_query_logins_response));
-       SBP2_DEBUG("sbp2_query_logins: reserved_resp_length initialized");
 
-       scsi_id->query_logins_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO +
-                                                   SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id);
-       scsi_id->query_logins_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
-                                                    SBP2_STATUS_FIFO_ADDRESS_HI);
-       SBP2_DEBUG("sbp2_query_logins: status FIFO initialized");
+       scsi_id->query_logins_orb->status_fifo_hi =
+               ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
+       scsi_id->query_logins_orb->status_fifo_lo =
+               ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);
 
        sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb));
 
-       SBP2_DEBUG("sbp2_query_logins: orb byte-swapped");
-
        sbp2util_packet_dump(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb),
                             "sbp2 query logins orb", scsi_id->query_logins_orb_dma);
 
        memset(scsi_id->query_logins_response, 0, sizeof(struct sbp2_query_logins_response));
        memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));
 
-       SBP2_DEBUG("sbp2_query_logins: query_logins_response/status FIFO memset");
-
        data[0] = ORB_SET_NODE_ID(hi->host->node_id);
        data[1] = scsi_id->query_logins_orb_dma;
        sbp2util_cpu_to_be32_buffer(data, 8);
 
        atomic_set(&scsi_id->sbp2_login_complete, 0);
 
-       SBP2_DEBUG("sbp2_query_logins: prepared to write");
        hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);
-       SBP2_DEBUG("sbp2_query_logins: written");
 
        if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 2*HZ)) {
                SBP2_INFO("Error querying logins to SBP-2 device - timed out");
@@ -1191,10 +1162,10 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
        struct sbp2scsi_host_info *hi = scsi_id->hi;
        quadlet_t data[2];
 
-       SBP2_DEBUG("sbp2_login_device");
+       SBP2_DEBUG_ENTER();
 
        if (!scsi_id->login_orb) {
-               SBP2_DEBUG("sbp2_login_device: login_orb not alloc'd!");
+               SBP2_DEBUG("%s: login_orb not alloc'd!", __FUNCTION__);
                return -EIO;
        }
 
@@ -1208,60 +1179,39 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
        /* Set-up login ORB, assume no password */
        scsi_id->login_orb->password_hi = 0;
        scsi_id->login_orb->password_lo = 0;
-       SBP2_DEBUG("sbp2_login_device: password_hi/lo initialized");
 
        scsi_id->login_orb->login_response_lo = scsi_id->login_response_dma;
        scsi_id->login_orb->login_response_hi = ORB_SET_NODE_ID(hi->host->node_id);
-       SBP2_DEBUG("sbp2_login_device: login_response_hi/lo initialized");
 
        scsi_id->login_orb->lun_misc = ORB_SET_FUNCTION(SBP2_LOGIN_REQUEST);
        scsi_id->login_orb->lun_misc |= ORB_SET_RECONNECT(0);   /* One second reconnect time */
        scsi_id->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(exclusive_login);     /* Exclusive access to device */
        scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1);      /* Notify us of login complete */
        scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun);
-       SBP2_DEBUG("sbp2_login_device: lun_misc initialized");
 
        scsi_id->login_orb->passwd_resp_lengths =
                ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response));
-       SBP2_DEBUG("sbp2_login_device: passwd_resp_lengths initialized");
 
-       scsi_id->login_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO +
-                                            SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id);
-       scsi_id->login_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
-                                             SBP2_STATUS_FIFO_ADDRESS_HI);
-       SBP2_DEBUG("sbp2_login_device: status FIFO initialized");
+       scsi_id->login_orb->status_fifo_hi =
+               ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
+       scsi_id->login_orb->status_fifo_lo =
+               ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);
 
-       /*
-        * Byte swap ORB if necessary
-        */
        sbp2util_cpu_to_be32_buffer(scsi_id->login_orb, sizeof(struct sbp2_login_orb));
 
-       SBP2_DEBUG("sbp2_login_device: orb byte-swapped");
-
        sbp2util_packet_dump(scsi_id->login_orb, sizeof(struct sbp2_login_orb),
                             "sbp2 login orb", scsi_id->login_orb_dma);
 
-       /*
-        * Initialize login response and status fifo
-        */
        memset(scsi_id->login_response, 0, sizeof(struct sbp2_login_response));
        memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));
 
-       SBP2_DEBUG("sbp2_login_device: login_response/status FIFO memset");
-
-       /*
-        * Ok, let's write to the target's management agent register
-        */
        data[0] = ORB_SET_NODE_ID(hi->host->node_id);
        data[1] = scsi_id->login_orb_dma;
        sbp2util_cpu_to_be32_buffer(data, 8);
 
        atomic_set(&scsi_id->sbp2_login_complete, 0);
 
-       SBP2_DEBUG("sbp2_login_device: prepared to write to %08x",
-                  (unsigned int)scsi_id->sbp2_management_agent_addr);
        hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);
-       SBP2_DEBUG("sbp2_login_device: written");
 
        /*
         * Wait for login status (up to 20 seconds)...
@@ -1325,7 +1275,7 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id)
        quadlet_t data[2];
        int error;
 
-       SBP2_DEBUG("sbp2_logout_device");
+       SBP2_DEBUG_ENTER();
 
        /*
         * Set-up logout ORB
@@ -1342,10 +1292,10 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id)
        scsi_id->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
 
        scsi_id->logout_orb->reserved5 = 0x0;
-       scsi_id->logout_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO +
-                                             SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id);
-       scsi_id->logout_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
-                                              SBP2_STATUS_FIFO_ADDRESS_HI);
+       scsi_id->logout_orb->status_fifo_hi =
+               ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
+       scsi_id->logout_orb->status_fifo_lo =
+               ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);
 
        /*
         * Byte swap ORB if necessary
@@ -1389,7 +1339,7 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
        quadlet_t data[2];
        int error;
 
-       SBP2_DEBUG("sbp2_reconnect_device");
+       SBP2_DEBUG_ENTER();
 
        /*
         * Set-up reconnect ORB
@@ -1407,10 +1357,10 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
        scsi_id->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
 
        scsi_id->reconnect_orb->reserved5 = 0x0;
-       scsi_id->reconnect_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO +
-                                                SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id);
-       scsi_id->reconnect_orb->status_FIFO_hi =
-               (ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI);
+       scsi_id->reconnect_orb->status_fifo_hi =
+               ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
+       scsi_id->reconnect_orb->status_fifo_lo =
+               ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);
 
        /*
         * Byte swap ORB if necessary
@@ -1480,17 +1430,11 @@ static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id)
 {
        quadlet_t data;
 
-       SBP2_DEBUG("sbp2_set_busy_timeout");
+       SBP2_DEBUG_ENTER();
 
-       /*
-        * Ok, let's write to the target's busy timeout register
-        */
        data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE);
-
-       if (hpsb_node_write(scsi_id->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) {
-               SBP2_ERR("sbp2_set_busy_timeout error");
-       }
-
+       if (hpsb_node_write(scsi_id->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4))
+               SBP2_ERR("%s error", __FUNCTION__);
        return 0;
 }
 
@@ -1509,7 +1453,7 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
            firmware_revision, workarounds;
        int i;
 
-       SBP2_DEBUG("sbp2_parse_unit_directory");
+       SBP2_DEBUG_ENTER();
 
        management_agent_addr = 0x0;
        command_set_spec_id = 0x0;
@@ -1601,7 +1545,7 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
        /* Check for a blacklisted set of devices that require us to force
         * a 36 byte host inquiry. This can be overriden as a module param
         * (to force all hosts).  */
-       for (i = 0; i < NUM_BROKEN_INQUIRY_DEVS; i++) {
+       for (i = 0; i < ARRAY_SIZE(sbp2_broken_inquiry_list); i++) {
                if ((firmware_revision & 0xffff00) ==
                                sbp2_broken_inquiry_list[i]) {
                        SBP2_WARN("Node " NODE_BUS_FMT ": Using 36byte inquiry workaround",
@@ -1642,7 +1586,7 @@ static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id)
 {
        struct sbp2scsi_host_info *hi = scsi_id->hi;
 
-       SBP2_DEBUG("sbp2_max_speed_and_size");
+       SBP2_DEBUG_ENTER();
 
        /* Initial setting comes from the hosts speed map */
        scsi_id->speed_code =
@@ -1679,11 +1623,8 @@ static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait)
        u64 addr;
        int retval;
 
-       SBP2_DEBUG("sbp2_agent_reset");
+       SBP2_DEBUG_ENTER();
 
-       /*
-        * Ok, let's write to the target's management agent register
-        */
        data = ntohl(SBP2_AGENT_RESET_DATA);
        addr = scsi_id->sbp2_command_block_agent_addr + SBP2_AGENT_RESET_OFFSET;
 
@@ -1705,26 +1646,184 @@ static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait)
        return 0;
 }
 
+static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
+                                    struct sbp2scsi_host_info *hi,
+                                    struct sbp2_command_info *command,
+                                    unsigned int scsi_use_sg,
+                                    struct scatterlist *sgpnt,
+                                    u32 orb_direction,
+                                    enum dma_data_direction dma_dir)
+{
+       command->dma_dir = dma_dir;
+       orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
+       orb->misc |= ORB_SET_DIRECTION(orb_direction);
+
+       /* Special case if only one element (and less than 64KB in size) */
+       if ((scsi_use_sg == 1) &&
+           (sgpnt[0].length <= SBP2_MAX_SG_ELEMENT_LENGTH)) {
+
+               SBP2_DEBUG("Only one s/g element");
+               command->dma_size = sgpnt[0].length;
+               command->dma_type = CMD_DMA_PAGE;
+               command->cmd_dma = pci_map_page(hi->host->pdev,
+                                               sgpnt[0].page,
+                                               sgpnt[0].offset,
+                                               command->dma_size,
+                                               command->dma_dir);
+               SBP2_DMA_ALLOC("single page scatter element");
+
+               orb->data_descriptor_lo = command->cmd_dma;
+               orb->misc |= ORB_SET_DATA_SIZE(command->dma_size);
+
+       } else {
+               struct sbp2_unrestricted_page_table *sg_element =
+                                       &command->scatter_gather_element[0];
+               u32 sg_count, sg_len;
+               dma_addr_t sg_addr;
+               int i, count = pci_map_sg(hi->host->pdev, sgpnt, scsi_use_sg,
+                                         dma_dir);
+
+               SBP2_DMA_ALLOC("scatter list");
+
+               command->dma_size = scsi_use_sg;
+               command->sge_buffer = sgpnt;
+
+               /* use page tables (s/g) */
+               orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
+               orb->data_descriptor_lo = command->sge_dma;
+
+               /*
+                * Loop through and fill out our sbp-2 page tables
+                * (and split up anything too large)
+                */
+               for (i = 0, sg_count = 0 ; i < count; i++, sgpnt++) {
+                       sg_len = sg_dma_len(sgpnt);
+                       sg_addr = sg_dma_address(sgpnt);
+                       while (sg_len) {
+                               sg_element[sg_count].segment_base_lo = sg_addr;
+                               if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
+                                       sg_element[sg_count].length_segment_base_hi =
+                                               PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
+                                       sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
+                                       sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
+                               } else {
+                                       sg_element[sg_count].length_segment_base_hi =
+                                               PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
+                                       sg_len = 0;
+                               }
+                               sg_count++;
+                       }
+               }
+
+               /* Number of page table (s/g) elements */
+               orb->misc |= ORB_SET_DATA_SIZE(sg_count);
+
+               sbp2util_packet_dump(sg_element,
+                                    (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,
+                                    "sbp2 s/g list", command->sge_dma);
+
+               /* Byte swap page tables if necessary */
+               sbp2util_cpu_to_be32_buffer(sg_element,
+                                           (sizeof(struct sbp2_unrestricted_page_table)) *
+                                           sg_count);
+       }
+}
+
+static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb,
+                                       struct sbp2scsi_host_info *hi,
+                                       struct sbp2_command_info *command,
+                                       struct scatterlist *sgpnt,
+                                       u32 orb_direction,
+                                       unsigned int scsi_request_bufflen,
+                                       void *scsi_request_buffer,
+                                       enum dma_data_direction dma_dir)
+{
+       command->dma_dir = dma_dir;
+       command->dma_size = scsi_request_bufflen;
+       command->dma_type = CMD_DMA_SINGLE;
+       command->cmd_dma = pci_map_single(hi->host->pdev, scsi_request_buffer,
+                                         command->dma_size, command->dma_dir);
+       orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
+       orb->misc |= ORB_SET_DIRECTION(orb_direction);
+
+       SBP2_DMA_ALLOC("single bulk");
+
+       /*
+        * Handle case where we get a command w/o s/g enabled (but
+        * check for transfers larger than 64K)
+        */
+       if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) {
+
+               orb->data_descriptor_lo = command->cmd_dma;
+               orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen);
+
+       } else {
+               struct sbp2_unrestricted_page_table *sg_element =
+                       &command->scatter_gather_element[0];
+               u32 sg_count, sg_len;
+               dma_addr_t sg_addr;
+
+               /*
+                * Need to turn this into page tables, since the
+                * buffer is too large.
+                */
+               orb->data_descriptor_lo = command->sge_dma;
+
+               /* Use page tables (s/g) */
+               orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
+
+               /*
+                * fill out our sbp-2 page tables (and split up
+                * the large buffer)
+                */
+               sg_count = 0;
+               sg_len = scsi_request_bufflen;
+               sg_addr = command->cmd_dma;
+               while (sg_len) {
+                       sg_element[sg_count].segment_base_lo = sg_addr;
+                       if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
+                               sg_element[sg_count].length_segment_base_hi =
+                                       PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
+                               sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
+                               sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
+                       } else {
+                               sg_element[sg_count].length_segment_base_hi =
+                                       PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
+                               sg_len = 0;
+                       }
+                       sg_count++;
+               }
+
+               /* Number of page table (s/g) elements */
+               orb->misc |= ORB_SET_DATA_SIZE(sg_count);
+
+               sbp2util_packet_dump(sg_element,
+                                    (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,
+                                    "sbp2 s/g list", command->sge_dma);
+
+               /* Byte swap page tables if necessary */
+               sbp2util_cpu_to_be32_buffer(sg_element,
+                                           (sizeof(struct sbp2_unrestricted_page_table)) *
+                                            sg_count);
+       }
+}
+
 /*
  * This function is called to create the actual command orb and s/g list
  * out of the scsi command itself.
  */
-static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
-                                  struct sbp2_command_info *command,
-                                  unchar *scsi_cmd,
-                                  unsigned int scsi_use_sg,
-                                  unsigned int scsi_request_bufflen,
-                                  void *scsi_request_buffer,
-                                  enum dma_data_direction dma_dir)
+static void sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
+                                   struct sbp2_command_info *command,
+                                   unchar *scsi_cmd,
+                                   unsigned int scsi_use_sg,
+                                   unsigned int scsi_request_bufflen,
+                                   void *scsi_request_buffer,
+                                   enum dma_data_direction dma_dir)
 {
        struct sbp2scsi_host_info *hi = scsi_id->hi;
        struct scatterlist *sgpnt = (struct scatterlist *)scsi_request_buffer;
        struct sbp2_command_orb *command_orb = &command->command_orb;
-       struct sbp2_unrestricted_page_table *scatter_gather_element =
-               &command->scatter_gather_element[0];
-       u32 sg_count, sg_len, orb_direction;
-       dma_addr_t sg_addr;
-       int i;
+       u32 orb_direction;
 
        /*
         * Set-up our command ORB..
@@ -1740,220 +1839,40 @@ static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
        command_orb->misc |= ORB_SET_SPEED(scsi_id->speed_code);
        command_orb->misc |= ORB_SET_NOTIFY(1); /* Notify us when complete */
 
-       /*
-        * Get the direction of the transfer. If the direction is unknown, then use our
-        * goofy table as a back-up.
-        */
-       switch (dma_dir) {
-       case DMA_NONE:
+       if (dma_dir == DMA_NONE)
                orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;
-               break;
-       case DMA_TO_DEVICE:
+       else if (dma_dir == DMA_TO_DEVICE && scsi_request_bufflen)
                orb_direction = ORB_DIRECTION_WRITE_TO_MEDIA;
-               break;
-       case DMA_FROM_DEVICE:
+       else if (dma_dir == DMA_FROM_DEVICE && scsi_request_bufflen)
                orb_direction = ORB_DIRECTION_READ_FROM_MEDIA;
-               break;
-       case DMA_BIDIRECTIONAL:
-       default:
-               SBP2_ERR("SCSI data transfer direction not specified. "
-                        "Update the SBP2 direction table in sbp2.h if "
-                        "necessary for your application");
-               __scsi_print_command(scsi_cmd);
-               orb_direction = sbp2scsi_direction_table[*scsi_cmd];
-               break;
+       else {
+               SBP2_WARN("Falling back to DMA_NONE");
+               orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;
        }
 
-       /*
-        * Set-up our pagetable stuff... unfortunately, this has become
-        * messier than I'd like. Need to clean this up a bit.   ;-)
-        */
+       /* Set-up our pagetable stuff */
        if (orb_direction == ORB_DIRECTION_NO_DATA_TRANSFER) {
-
                SBP2_DEBUG("No data transfer");
-
-               /*
-                * Handle no data transfer
-                */
                command_orb->data_descriptor_hi = 0x0;
                command_orb->data_descriptor_lo = 0x0;
                command_orb->misc |= ORB_SET_DIRECTION(1);
-
        } else if (scsi_use_sg) {
-
                SBP2_DEBUG("Use scatter/gather");
-
-               /*
-                * Special case if only one element (and less than 64KB in size)
-                */
-               if ((scsi_use_sg == 1) && (sgpnt[0].length <= SBP2_MAX_SG_ELEMENT_LENGTH)) {
-
-                       SBP2_DEBUG("Only one s/g element");
-                       command->dma_dir = dma_dir;
-                       command->dma_size = sgpnt[0].length;
-                       command->dma_type = CMD_DMA_PAGE;
-                       command->cmd_dma = pci_map_page(hi->host->pdev,
-                                                       sgpnt[0].page,
-                                                       sgpnt[0].offset,
-                                                       command->dma_size,
-                                                       command->dma_dir);
-                       SBP2_DMA_ALLOC("single page scatter element");
-
-                       command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
-                       command_orb->data_descriptor_lo = command->cmd_dma;
-                       command_orb->misc |= ORB_SET_DATA_SIZE(command->dma_size);
-                       command_orb->misc |= ORB_SET_DIRECTION(orb_direction);
-
-               } else {
-                       int count = pci_map_sg(hi->host->pdev, sgpnt, scsi_use_sg, dma_dir);
-                       SBP2_DMA_ALLOC("scatter list");
-
-                       command->dma_size = scsi_use_sg;
-                       command->dma_dir = dma_dir;
-                       command->sge_buffer = sgpnt;
-
-                       /* use page tables (s/g) */
-                       command_orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
-                       command_orb->misc |= ORB_SET_DIRECTION(orb_direction);
-                       command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
-                       command_orb->data_descriptor_lo = command->sge_dma;
-
-                       /*
-                        * Loop through and fill out our sbp-2 page tables
-                        * (and split up anything too large)
-                        */
-                       for (i = 0, sg_count = 0 ; i < count; i++, sgpnt++) {
-                               sg_len = sg_dma_len(sgpnt);
-                               sg_addr = sg_dma_address(sgpnt);
-                               while (sg_len) {
-                                       scatter_gather_element[sg_count].segment_base_lo = sg_addr;
-                                       if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
-                                               scatter_gather_element[sg_count].length_segment_base_hi =
-                                                       PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
-                                               sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
-                                               sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
-                                       } else {
-                                               scatter_gather_element[sg_count].length_segment_base_hi =
-                                                       PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
-                                               sg_len = 0;
-                                       }
-                                       sg_count++;
-                               }
-                       }
-
-                       /* Number of page table (s/g) elements */
-                       command_orb->misc |= ORB_SET_DATA_SIZE(sg_count);
-
-                       sbp2util_packet_dump(scatter_gather_element,
-                                            (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,
-                                            "sbp2 s/g list", command->sge_dma);
-
-                       /*
-                        * Byte swap page tables if necessary
-                        */
-                       sbp2util_cpu_to_be32_buffer(scatter_gather_element,
-                                                   (sizeof(struct sbp2_unrestricted_page_table)) *
-                                                   sg_count);
-
-               }
-
+               sbp2_prep_command_orb_sg(command_orb, hi, command, scsi_use_sg,
+                                        sgpnt, orb_direction, dma_dir);
        } else {
-
                SBP2_DEBUG("No scatter/gather");
-
-               command->dma_dir = dma_dir;
-               command->dma_size = scsi_request_bufflen;
-               command->dma_type = CMD_DMA_SINGLE;
-               command->cmd_dma =
-                   pci_map_single(hi->host->pdev, scsi_request_buffer,
-                                  command->dma_size, command->dma_dir);
-               SBP2_DMA_ALLOC("single bulk");
-
-               /*
-                * Handle case where we get a command w/o s/g enabled (but
-                * check for transfers larger than 64K)
-                */
-               if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) {
-
-                       command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
-                       command_orb->data_descriptor_lo = command->cmd_dma;
-                       command_orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen);
-                       command_orb->misc |= ORB_SET_DIRECTION(orb_direction);
-
-                       /*
-                        * Sanity, in case our direction table is not
-                        * up-to-date
-                        */
-                       if (!scsi_request_bufflen) {
-                               command_orb->data_descriptor_hi = 0x0;
-                               command_orb->data_descriptor_lo = 0x0;
-                               command_orb->misc |= ORB_SET_DIRECTION(1);
-                       }
-
-               } else {
-                       /*
-                        * Need to turn this into page tables, since the
-                        * buffer is too large.
-                        */
-                       command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
-                       command_orb->data_descriptor_lo = command->sge_dma;
-
-                       /* Use page tables (s/g) */
-                       command_orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
-                       command_orb->misc |= ORB_SET_DIRECTION(orb_direction);
-
-                       /*
-                        * fill out our sbp-2 page tables (and split up
-                        * the large buffer)
-                        */
-                       sg_count = 0;
-                       sg_len = scsi_request_bufflen;
-                       sg_addr = command->cmd_dma;
-                       while (sg_len) {
-                               scatter_gather_element[sg_count].segment_base_lo = sg_addr;
-                               if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
-                                       scatter_gather_element[sg_count].length_segment_base_hi =
-                                               PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
-                                       sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
-                                       sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
-                               } else {
-                                       scatter_gather_element[sg_count].length_segment_base_hi =
-                                               PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
-                                       sg_len = 0;
-                               }
-                               sg_count++;
-                       }
-
-                       /* Number of page table (s/g) elements */
-                       command_orb->misc |= ORB_SET_DATA_SIZE(sg_count);
-
-                       sbp2util_packet_dump(scatter_gather_element,
-                                            (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,
-                                            "sbp2 s/g list", command->sge_dma);
-
-                       /*
-                        * Byte swap page tables if necessary
-                        */
-                       sbp2util_cpu_to_be32_buffer(scatter_gather_element,
-                                                   (sizeof(struct sbp2_unrestricted_page_table)) *
-                                                    sg_count);
-
-               }
-
+               sbp2_prep_command_orb_no_sg(command_orb, hi, command, sgpnt,
+                                           orb_direction, scsi_request_bufflen,
+                                           scsi_request_buffer, dma_dir);
        }
 
-       /*
-        * Byte swap command ORB if necessary
-        */
+       /* Byte swap command ORB if necessary */
        sbp2util_cpu_to_be32_buffer(command_orb, sizeof(struct sbp2_command_orb));
 
-       /*
-        * Put our scsi command in the command ORB
-        */
+       /* Put our scsi command in the command ORB */
        memset(command_orb->cdb, 0, 12);
        memcpy(command_orb->cdb, scsi_cmd, COMMAND_SIZE(*scsi_cmd));
-
-       return 0;
 }
 
 /*
@@ -2053,11 +1972,7 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
        unsigned int request_bufflen = SCpnt->request_bufflen;
        struct sbp2_command_info *command;
 
-       SBP2_DEBUG("sbp2_send_command");
-#if (CONFIG_IEEE1394_SBP2_DEBUG >= 2) || defined(CONFIG_IEEE1394_SBP2_PACKET_DUMP)
-       printk("[scsi command]\n   ");
-       scsi_print_command(SCpnt);
-#endif
+       SBP2_DEBUG_ENTER();
        SBP2_DEBUG("SCSI transfer size = %x", request_bufflen);
        SBP2_DEBUG("SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg);
 
@@ -2069,18 +1984,6 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
                return -EIO;
        }
 
-       /*
-        * The scsi stack sends down a request_bufflen which does not match the
-        * length field in the scsi cdb. This causes some sbp2 devices to
-        * reject this inquiry command. Fix the request_bufflen.
-        */
-       if (*cmd == INQUIRY) {
-               if (force_inquiry_hack || scsi_id->workarounds & SBP2_BREAKAGE_INQUIRY_HACK)
-                       request_bufflen = cmd[4] = 0x24;
-               else
-                       request_bufflen = cmd[4];
-       }
-
        /*
         * Now actually fill in the comamnd orb and sbp2 s/g list
         */
@@ -2109,7 +2012,7 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
  */
 static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data)
 {
-       SBP2_DEBUG("sbp2_status_to_sense_data");
+       SBP2_DEBUG_ENTER();
 
        /*
         * Ok, it's pretty ugly...   ;-)
@@ -2143,11 +2046,9 @@ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
 {
        u8 *scsi_buf = SCpnt->request_buffer;
 
-       SBP2_DEBUG("sbp2_check_sbp2_response");
-
-       switch (SCpnt->cmnd[0]) {
+       SBP2_DEBUG_ENTER();
 
-       case INQUIRY:
+       if (SCpnt->cmnd[0] == INQUIRY && (SCpnt->cmnd[1] & 3) == 0) {
                /*
                 * Make sure data length is ok. Minimum length is 36 bytes
                 */
@@ -2160,13 +2061,7 @@ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
                 */
                scsi_buf[2] |= 2;
                scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2;
-
-               break;
-
-       default:
-               break;
        }
-       return;
 }
 
 /*
@@ -2177,13 +2072,12 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
 {
        struct sbp2scsi_host_info *hi;
        struct scsi_id_instance_data *scsi_id = NULL, *scsi_id_tmp;
-       u32 id;
        struct scsi_cmnd *SCpnt = NULL;
        u32 scsi_status = SBP2_SCSI_STATUS_GOOD;
        struct sbp2_command_info *command;
        unsigned long flags;
 
-       SBP2_DEBUG("sbp2_handle_status_write");
+       SBP2_DEBUG_ENTER();
 
        sbp2util_packet_dump(data, length, "sbp2 status write by device", (u32)addr);
 
@@ -2200,12 +2094,12 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
        }
 
        /*
-        * Find our scsi_id structure by looking at the status fifo address written to by
-        * the sbp2 device.
+        * Find our scsi_id structure by looking at the status fifo address
+        * written to by the sbp2 device.
         */
-       id = SBP2_STATUS_FIFO_OFFSET_TO_ENTRY((u32)(addr - SBP2_STATUS_FIFO_ADDRESS));
        list_for_each_entry(scsi_id_tmp, &hi->scsi_ids, scsi_list) {
-               if (scsi_id_tmp->ne->nodeid == nodeid && scsi_id_tmp->ud->id == id) {
+               if (scsi_id_tmp->ne->nodeid == nodeid &&
+                   scsi_id_tmp->status_fifo_addr == addr) {
                        scsi_id = scsi_id_tmp;
                        break;
                }
@@ -2247,7 +2141,9 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
                 * Matched status with command, now grab scsi command pointers and check status
                 */
                SCpnt = command->Current_SCpnt;
+               spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
                sbp2util_mark_command_completed(scsi_id, command);
+               spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 
                if (SCpnt) {
 
@@ -2330,7 +2226,10 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
        struct sbp2scsi_host_info *hi;
        int result = DID_NO_CONNECT << 16;
 
-       SBP2_DEBUG("sbp2scsi_queuecommand");
+       SBP2_DEBUG_ENTER();
+#if (CONFIG_IEEE1394_SBP2_DEBUG >= 2) || defined(CONFIG_IEEE1394_SBP2_PACKET_DUMP)
+       scsi_print_command(SCpnt);
+#endif
 
        if (!sbp2util_node_is_available(scsi_id))
                goto done;
@@ -2370,6 +2269,16 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
                goto done;
        }
 
+       /*
+        * Bidirectional commands are not yet implemented,
+        * and unknown transfer direction not handled.
+        */
+       if (SCpnt->sc_data_direction == DMA_BIDIRECTIONAL) {
+               SBP2_ERR("Cannot handle DMA_BIDIRECTIONAL - rejecting command");
+               result = DID_ERROR << 16;
+               goto done;
+       }
+
        /*
         * Try and send our SCSI command
         */
@@ -2398,7 +2307,7 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id
        struct sbp2_command_info *command;
        unsigned long flags;
 
-       SBP2_DEBUG("sbp2scsi_complete_all_commands");
+       SBP2_DEBUG_ENTER();
 
        spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
        while (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
@@ -2431,7 +2340,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
                                      u32 scsi_status, struct scsi_cmnd *SCpnt,
                                      void (*done)(struct scsi_cmnd *))
 {
-       SBP2_DEBUG("sbp2scsi_complete_command");
+       SBP2_DEBUG_ENTER();
 
        /*
         * Sanity
@@ -2457,7 +2366,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
         */
        switch (scsi_status) {
        case SBP2_SCSI_STATUS_GOOD:
-               SCpnt->result = DID_OK;
+               SCpnt->result = DID_OK << 16;
                break;
 
        case SBP2_SCSI_STATUS_BUSY:
@@ -2467,16 +2376,11 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
 
        case SBP2_SCSI_STATUS_CHECK_CONDITION:
                SBP2_DEBUG("SBP2_SCSI_STATUS_CHECK_CONDITION");
-               SCpnt->result = CHECK_CONDITION << 1;
-
-               /*
-                * Debug stuff
-                */
+               SCpnt->result = CHECK_CONDITION << 1 | DID_OK << 16;
 #if CONFIG_IEEE1394_SBP2_DEBUG >= 1
                scsi_print_command(SCpnt);
-               scsi_print_sense("bh", SCpnt);
+               scsi_print_sense(SBP2_DEVICE_NAME, SCpnt);
 #endif
-
                break;
 
        case SBP2_SCSI_STATUS_SELECTION_TIMEOUT:
@@ -2501,7 +2405,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
        /*
         * Take care of any sbp2 response data mucking here (RBC stuff, etc.)
         */
-       if (SCpnt->result == DID_OK) {
+       if (SCpnt->result == DID_OK << 16) {
                sbp2_check_sbp2_response(scsi_id, SCpnt);
        }
 
@@ -2519,6 +2423,8 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
         * If a unit attention occurs, return busy status so it gets
         * retried... it could have happened because of a 1394 bus reset
         * or hot-plug...
+        * XXX  DID_BUS_BUSY is actually a bad idea because it will defy
+        * the scsi layer's retry logic.
         */
 #if 0
        if ((scsi_status == SBP2_SCSI_STATUS_CHECK_CONDITION) &&
@@ -2536,7 +2442,16 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
 
 static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
 {
-       ((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = sdev;
+       struct scsi_id_instance_data *scsi_id =
+               (struct scsi_id_instance_data *)sdev->host->hostdata[0];
+
+       scsi_id->sdev = sdev;
+
+       if (force_inquiry_hack ||
+           scsi_id->workarounds & SBP2_BREAKAGE_INQUIRY_HACK) {
+               sdev->inquiry_len = 36;
+               sdev->skip_ms_page_8 = 1;
+       }
        return 0;
 }
 
@@ -2564,6 +2479,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
                (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
        struct sbp2scsi_host_info *hi = scsi_id->hi;
        struct sbp2_command_info *command;
+       unsigned long flags;
 
        SBP2_ERR("aborting sbp2 command");
        scsi_print_command(SCpnt);
@@ -2574,6 +2490,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
                 * Right now, just return any matching command structures
                 * to the free pool.
                 */
+               spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
                command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt);
                if (command) {
                        SBP2_DEBUG("Found command to abort");
@@ -2591,6 +2508,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
                                command->Current_done(command->Current_SCpnt);
                        }
                }
+               spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 
                /*
                 * Initiate a fetch agent reset.
@@ -2675,7 +2593,7 @@ static int sbp2_module_init(void)
 {
        int ret;
 
-       SBP2_DEBUG("sbp2_module_init");
+       SBP2_DEBUG_ENTER();
 
        /* Module load debug option to force one command at a time (serializing I/O) */
        if (serialize_io) {
@@ -2703,7 +2621,7 @@ static int sbp2_module_init(void)
 
 static void __exit sbp2_module_exit(void)
 {
-       SBP2_DEBUG("sbp2_module_exit");
+       SBP2_DEBUG_ENTER();
 
        hpsb_unregister_protocol(&sbp2_driver);