* but the code needs additional debugging.
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/string.h>
-#include <linux/stringify.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
*/
static int max_sectors = SBP2_MAX_SECTORS;
module_param(max_sectors, int, 0444);
-MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported (default = "
- __stringify(SBP2_MAX_SECTORS) ")");
+MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported (default = 255)");
/*
* Exclusive login to sbp2 device? In most cases, the sbp2 driver should
* talking to a single sbp2 device at the same time (filesystem coherency,
* etc.). If you're running an sbp2 device that supports multiple logins,
* and you're either running read-only filesystems or some sort of special
- * filesystem supporting multiple hosts, e.g. OpenGFS, Oracle Cluster
- * File System, or Lustre, then set exclusive_login to zero.
- *
- * So far only bridges from Oxford Semiconductor are known to support
- * concurrent logins. Depending on firmware, four or two concurrent logins
- * are possible on OXFW911 and newer Oxsemi bridges.
+ * filesystem supporting multiple hosts (one such filesystem is OpenGFS,
+ * see opengfs.sourceforge.net for more info), then set exclusive_login
+ * to zero. Note: The Oxsemi OXFW911 sbp2 chipset supports up to four
+ * concurrent logins.
*/
static int exclusive_login = 1;
module_param(exclusive_login, int, 0644);
MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device (default = 1)");
/*
- * If any of the following workarounds is required for your device to work,
- * please submit the kernel messages logged by sbp2 to the linux1394-devel
- * mailing list.
- *
- * - 128kB max transfer
- * Limit transfer size. Necessary for some old bridges.
- *
- * - 36 byte inquiry
- * When scsi_mod probes the device, let the inquiry command look like that
- * from MS Windows.
+ * 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
+ * by enforcing 36 byte inquiry and avoiding access to mode_sense page 8.
*
- * - skip mode page 8
- * Suppress sending of mode_sense for mode page 8 if the device pretends to
- * support the SCSI Primary Block commands instead of Reduced Block Commands.
- *
- * - fix capacity
- * Tell sd_mod to correct the last sector number reported by read_capacity.
- * Avoids access beyond actual disk limits on devices with an off-by-one bug.
- * Don't use this with devices which don't have this bug.
- *
- * - override internal blacklist
- * Instead of adding to the built-in blacklist, use only the workarounds
- * specified in the module load parameter.
- * Useful if a blacklist entry interfered with a non-broken device.
+ * 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 sbp2_default_workarounds;
-module_param_named(workarounds, sbp2_default_workarounds, int, 0644);
-MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0"
- ", 128kB max transfer = " __stringify(SBP2_WORKAROUND_128K_MAX_TRANS)
- ", 36 byte inquiry = " __stringify(SBP2_WORKAROUND_INQUIRY_36)
- ", skip mode page 8 = " __stringify(SBP2_WORKAROUND_MODE_SENSE_8)
- ", fix capacity = " __stringify(SBP2_WORKAROUND_FIX_CAPACITY)
- ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
- ", or a combination)");
-
-/* legacy parameter */
static int force_inquiry_hack;
module_param(force_inquiry_hack, int, 0644);
-MODULE_PARM_DESC(force_inquiry_hack, "Deprecated, use 'workarounds'");
+MODULE_PARM_DESC(force_inquiry_hack, "Force SCSI inquiry hack (default = 0)");
/*
* Export information about protocols/devices supported by this driver.
#endif
#define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args)
-#define SBP2_DEBUG_ENTER() SBP2_DEBUG("%s", __FUNCTION__)
/*
* Globals
};
/*
- * List of devices with known bugs.
- *
- * The firmware_revision field, masked with 0xffff00, is the best indicator
- * for the type of bridge chip of a device. It yields a few false positives
- * but this did not break correctly behaving devices so far.
+ * List of device firmwares that require the inquiry hack.
+ * Yields a few false positives but did not break other devices so far.
*/
-static const struct {
- u32 firmware_revision;
- u32 model_id;
- unsigned workarounds;
-} sbp2_workarounds_table[] = {
- /* DViCO Momobay CX-1 with TSB42AA9 bridge */ {
- .firmware_revision = 0x002800,
- .model_id = 0x001010,
- .workarounds = SBP2_WORKAROUND_INQUIRY_36 |
- SBP2_WORKAROUND_MODE_SENSE_8,
- },
- /* Initio bridges, actually only needed for some older ones */ {
- .firmware_revision = 0x000200,
- .workarounds = SBP2_WORKAROUND_INQUIRY_36,
- },
- /* Symbios bridge */ {
- .firmware_revision = 0xa0b800,
- .workarounds = SBP2_WORKAROUND_128K_MAX_TRANS,
- },
- /*
- * Note about the following Apple iPod blacklist entries:
- *
- * There are iPods (2nd gen, 3rd gen) with model_id==0. Since our
- * matching logic treats 0 as a wildcard, we cannot match this ID
- * without rewriting the matching routine. Fortunately these iPods
- * do not feature the read_capacity bug according to one report.
- * Read_capacity behaviour as well as model_id could change due to
- * Apple-supplied firmware updates though.
- */
- /* iPod 4th generation */ {
- .firmware_revision = 0x0a2700,
- .model_id = 0x000021,
- .workarounds = SBP2_WORKAROUND_FIX_CAPACITY,
- },
- /* iPod mini */ {
- .firmware_revision = 0x0a2700,
- .model_id = 0x000023,
- .workarounds = SBP2_WORKAROUND_FIX_CAPACITY,
- },
- /* iPod Photo */ {
- .firmware_revision = 0x0a2700,
- .model_id = 0x00007e,
- .workarounds = SBP2_WORKAROUND_FIX_CAPACITY,
- }
+static u32 sbp2_broken_inquiry_list[] = {
+ 0x00002800, /* Stefan Richter <stefanr@s5r6.in-berlin.de> */
+ /* DViCO Momobay CX-1 */
+ 0x00000200 /* Andreas Plesch <plesch@fas.harvard.edu> */
+ /* QPS Fire DVDBurner */
};
/**************************************
command->Current_SCpnt = Current_SCpnt;
list_add_tail(&command->list, &scsi_id->sbp2_command_orb_inuse);
} else {
- SBP2_ERR("%s: no orbs available", __FUNCTION__);
+ SBP2_ERR("sbp2util_allocate_command_orb - No orbs available!");
}
spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
return command;
struct hpsb_host *host;
if (!scsi_id) {
- SBP2_ERR("%s: scsi_id == NULL", __FUNCTION__);
+ printk(KERN_ERR "%s: scsi_id == NULL\n", __FUNCTION__);
return;
}
struct unit_directory *ud;
struct scsi_id_instance_data *scsi_id;
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2_probe");
ud = container_of(dev, struct unit_directory, device);
struct scsi_id_instance_data *scsi_id;
struct scsi_device *sdev;
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2_remove");
ud = container_of(dev, struct unit_directory, device);
scsi_id = ud->device.driver_data;
{
struct scsi_id_instance_data *scsi_id = ud->device.driver_data;
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2_update");
if (sbp2_reconnect_device(scsi_id)) {
struct Scsi_Host *scsi_host = NULL;
struct scsi_id_instance_data *scsi_id = NULL;
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2_alloc_device");
scsi_id = kzalloc(sizeof(*scsi_id), GFP_KERNEL);
if (!scsi_id) {
scsi_id->ud = ud;
scsi_id->speed_code = IEEE1394_SPEED_100;
scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100];
- scsi_id->status_fifo_addr = CSR1212_INVALID_ADDR_SPACE;
atomic_set(&scsi_id->sbp2_login_complete, 0);
INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse);
INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed);
INIT_LIST_HEAD(&scsi_id->scsi_list);
spin_lock_init(&scsi_id->sbp2_command_orb_lock);
+ scsi_id->sbp2_lun = 0;
ud->device.driver_data = scsi_id;
#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
/* Handle data movement if physical dma is not
- * 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;
- }
+ * enabled/supportedon host controller */
+ hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, &sbp2_physdma_ops,
+ 0x0ULL, 0xfffffffcULL);
#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);
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),
- ud->ne->host->low_addr_space, CSR1212_ALL_SPACE_END);
- if (scsi_id->status_fifo_addr == CSR1212_INVALID_ADDR_SPACE) {
+ 0x010000000000ULL, CSR1212_ALL_SPACE_END);
+ if (scsi_id->status_fifo_addr == ~0ULL) {
SBP2_ERR("failed to allocate status FIFO address range");
goto failed_alloc;
}
struct sbp2scsi_host_info *hi = scsi_id->hi;
int error;
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2_start_device");
/* Login FIFO DMA */
scsi_id->login_response =
* 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;
}
{
struct sbp2scsi_host_info *hi;
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2_remove_device");
if (!scsi_id)
return;
SBP2_DMA_FREE("single query logins data");
}
- if (scsi_id->status_fifo_addr != CSR1212_INVALID_ADDR_SPACE)
+ if (scsi_id->status_fifo_addr)
hpsb_unregister_addrspace(&sbp2_highlevel, hi->host,
- scsi_id->status_fifo_addr);
+ 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);
int max_logins;
int active_logins;
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2_query_logins");
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_hi =
ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
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");
SBP2_DEBUG("length_max_logins = %x",
(unsigned int)scsi_id->query_logins_response->length_max_logins);
+ SBP2_DEBUG("Query logins to SBP-2 device successful");
+
max_logins = RESPONSE_GET_MAX_LOGINS(scsi_id->query_logins_response->length_max_logins);
- SBP2_INFO("Maximum concurrent logins supported: %d", max_logins);
+ SBP2_DEBUG("Maximum concurrent logins supported: %d", max_logins);
active_logins = RESPONSE_GET_ACTIVE_LOGINS(scsi_id->query_logins_response->length_max_logins);
- SBP2_INFO("Number of active logins: %d", active_logins);
+ SBP2_DEBUG("Number of active logins: %d", active_logins);
if (active_logins >= max_logins) {
return -EIO;
struct sbp2scsi_host_info *hi = scsi_id->hi;
quadlet_t data[2];
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2_login_device");
if (!scsi_id->login_orb) {
- SBP2_DEBUG("%s: login_orb not alloc'd!", __FUNCTION__);
+ SBP2_DEBUG("sbp2_login_device: login_orb not alloc'd!");
return -EIO;
}
/* 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_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)...
quadlet_t data[2];
int error;
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2_logout_device");
/*
* Set-up logout ORB
quadlet_t data[2];
int error;
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2_reconnect_device");
/*
* Set-up reconnect ORB
{
quadlet_t data;
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2_set_busy_timeout");
+ /*
+ * 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("%s error", __FUNCTION__);
+
+ if (hpsb_node_write(scsi_id->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) {
+ SBP2_ERR("sbp2_set_busy_timeout error");
+ }
+
return 0;
}
struct csr1212_dentry *dentry;
u64 management_agent_addr;
u32 command_set_spec_id, command_set, unit_characteristics,
- firmware_revision;
- unsigned workarounds;
+ firmware_revision, workarounds;
int i;
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2_parse_unit_directory");
management_agent_addr = 0x0;
command_set_spec_id = 0x0;
case SBP2_FIRMWARE_REVISION_KEY:
/* Firmware revision */
firmware_revision = kv->value.immediate;
- SBP2_DEBUG("sbp2_firmware_revision = %x",
- (unsigned int)firmware_revision);
+ if (force_inquiry_hack)
+ SBP2_INFO("sbp2_firmware_revision = %x",
+ (unsigned int)firmware_revision);
+ else
+ SBP2_DEBUG("sbp2_firmware_revision = %x",
+ (unsigned int)firmware_revision);
break;
default:
}
}
- workarounds = sbp2_default_workarounds;
- if (force_inquiry_hack) {
- SBP2_WARN("force_inquiry_hack is deprecated. "
- "Use parameter 'workarounds' instead.");
- workarounds |= SBP2_WORKAROUND_INQUIRY_36;
- }
+ /* This is the start of our broken device checking. We try to hack
+ * around oddities and known defects. */
+ workarounds = 0x0;
- if (!(workarounds & SBP2_WORKAROUND_OVERRIDE))
- for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) {
- if (sbp2_workarounds_table[i].firmware_revision &&
- sbp2_workarounds_table[i].firmware_revision !=
- (firmware_revision & 0xffff00))
- continue;
- if (sbp2_workarounds_table[i].model_id &&
- sbp2_workarounds_table[i].model_id != ud->model_id)
- continue;
- workarounds |= sbp2_workarounds_table[i].workarounds;
- break;
+ /* If the vendor id is 0xa0b8 (Symbios vendor id), then we have a
+ * bridge with 128KB max transfer size limitation. For sanity, we
+ * only voice this when the current max_sectors setting
+ * exceeds the 128k limit. By default, that is not the case.
+ *
+ * It would be really nice if we could detect this before the scsi
+ * host gets initialized. That way we can down-force the
+ * max_sectors to account for it. That is not currently
+ * possible. */
+ if ((firmware_revision & 0xffff00) ==
+ SBP2_128KB_BROKEN_FIRMWARE &&
+ (max_sectors * 512) > (128*1024)) {
+ SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB max transfer size.",
+ NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid));
+ SBP2_WARN("WARNING: Current max_sectors setting is larger than 128KB (%d sectors)!",
+ max_sectors);
+ workarounds |= SBP2_BREAKAGE_128K_MAX_TRANSFER;
+ }
+
+ /* 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 < 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",
+ NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid));
+ workarounds |= SBP2_BREAKAGE_INQUIRY_HACK;
+ break; /* No need to continue. */
}
-
- if (workarounds)
- SBP2_INFO("Workarounds for node " NODE_BUS_FMT ": 0x%x "
- "(firmware_revision 0x%06x, vendor_id 0x%06x,"
- " model_id 0x%06x)",
- NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid),
- workarounds, firmware_revision,
- ud->vendor_id ? ud->vendor_id : ud->ne->vendor_id,
- ud->model_id);
-
- /* We would need one SCSI host template for each target to adjust
- * max_sectors on the fly, therefore warn only. */
- if (workarounds & SBP2_WORKAROUND_128K_MAX_TRANS &&
- (max_sectors * 512) > (128 * 1024))
- SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB "
- "max transfer size. WARNING: Current max_sectors "
- "setting is larger than 128KB (%d sectors)",
- NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid),
- max_sectors);
+ }
/* If this is a logical unit directory entry, process the parent
* to get the values. */
}
}
-#define SBP2_PAYLOAD_TO_BYTES(p) (1 << ((p) + 2))
-
/*
* This function is called in order to determine the max speed and packet
* size we can use in our ORBs. Note, that we (the driver and host) only
static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id)
{
struct sbp2scsi_host_info *hi = scsi_id->hi;
- u8 payload;
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2_max_speed_and_size");
+ /* Initial setting comes from the hosts speed map */
scsi_id->speed_code =
- hi->host->speed[NODEID_TO_NODE(scsi_id->ne->nodeid)];
+ hi->host->speed_map[NODEID_TO_NODE(hi->host->node_id) * 64 +
+ NODEID_TO_NODE(scsi_id->ne->nodeid)];
/* Bump down our speed if the user requested it */
if (scsi_id->speed_code > max_speed) {
/* Payload size is the lesser of what our speed supports and what
* our host supports. */
- payload = min(sbp2_speedto_max_payload[scsi_id->speed_code],
- (u8) (hi->host->csr.max_rec - 1));
-
- /* If physical DMA is off, work around limitation in ohci1394:
- * packet size must not exceed PAGE_SIZE */
- if (scsi_id->ne->host->low_addr_space < (1ULL << 32))
- while (SBP2_PAYLOAD_TO_BYTES(payload) + 24 > PAGE_SIZE &&
- payload)
- payload--;
+ scsi_id->max_payload_size =
+ min(sbp2_speedto_max_payload[scsi_id->speed_code],
+ (u8) (hi->host->csr.max_rec - 1));
HPSB_DEBUG("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]",
NODE_BUS_ARGS(hi->host, scsi_id->ne->nodeid),
hpsb_speedto_str[scsi_id->speed_code],
- SBP2_PAYLOAD_TO_BYTES(payload));
+ 1 << ((u32) scsi_id->max_payload_size + 2));
- scsi_id->max_payload_size = payload;
return 0;
}
u64 addr;
int retval;
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2_agent_reset");
+ /*
+ * 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;
unsigned int request_bufflen = SCpnt->request_bufflen;
struct sbp2_command_info *command;
- SBP2_DEBUG_ENTER();
+ 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("SCSI transfer size = %x", request_bufflen);
SBP2_DEBUG("SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg);
*/
static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data)
{
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2_status_to_sense_data");
/*
* Ok, it's pretty ugly... ;-)
return sbp2_status[8] & 0x3f; /* return scsi status */
}
+/*
+ * This function is called after a command is completed, in order to do any necessary SBP-2
+ * response data translations for the SCSI stack
+ */
+static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
+ struct scsi_cmnd *SCpnt)
+{
+ u8 *scsi_buf = SCpnt->request_buffer;
+
+ SBP2_DEBUG("sbp2_check_sbp2_response");
+
+ if (SCpnt->cmnd[0] == INQUIRY && (SCpnt->cmnd[1] & 3) == 0) {
+ /*
+ * Make sure data length is ok. Minimum length is 36 bytes
+ */
+ if (scsi_buf[4] == 0) {
+ scsi_buf[4] = 36 - 5;
+ }
+
+ /*
+ * Fix ansi revision and response data format
+ */
+ scsi_buf[2] |= 2;
+ scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2;
+ }
+}
+
/*
* This function deals with status writes from the SBP-2 device
*/
struct sbp2_command_info *command;
unsigned long flags;
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2_handle_status_write");
sbp2util_packet_dump(data, length, "sbp2 status write by device", (u32)addr);
struct sbp2scsi_host_info *hi;
int result = DID_NO_CONNECT << 16;
- SBP2_DEBUG_ENTER();
-#if (CONFIG_IEEE1394_SBP2_DEBUG >= 2) || defined(CONFIG_IEEE1394_SBP2_PACKET_DUMP)
- scsi_print_command(SCpnt);
-#endif
+ SBP2_DEBUG("sbp2scsi_queuecommand");
if (!sbp2util_node_is_available(scsi_id))
goto done;
struct sbp2_command_info *command;
unsigned long flags;
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2scsi_complete_all_commands");
spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
while (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
u32 scsi_status, struct scsi_cmnd *SCpnt,
void (*done)(struct scsi_cmnd *))
{
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2scsi_complete_command");
/*
* Sanity
*/
switch (scsi_status) {
case SBP2_SCSI_STATUS_GOOD:
- SCpnt->result = DID_OK << 16;
+ SCpnt->result = DID_OK;
break;
case SBP2_SCSI_STATUS_BUSY:
case SBP2_SCSI_STATUS_CHECK_CONDITION:
SBP2_DEBUG("SBP2_SCSI_STATUS_CHECK_CONDITION");
- SCpnt->result = CHECK_CONDITION << 1 | DID_OK << 16;
+ SCpnt->result = CHECK_CONDITION << 1;
+
+ /*
+ * Debug stuff
+ */
#if CONFIG_IEEE1394_SBP2_DEBUG >= 1
scsi_print_command(SCpnt);
- scsi_print_sense(SBP2_DEVICE_NAME, SCpnt);
+ scsi_print_sense("bh", SCpnt);
#endif
+
break;
case SBP2_SCSI_STATUS_SELECTION_TIMEOUT:
SCpnt->result = DID_ERROR << 16;
}
+ /*
+ * Take care of any sbp2 response data mucking here (RBC stuff, etc.)
+ */
+ if (SCpnt->result == DID_OK) {
+ sbp2_check_sbp2_response(scsi_id, SCpnt);
+ }
+
/*
* If a bus reset is in progress and there was an error, complete
* the command as busy so that it will get retried.
* 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) &&
scsi_id->sdev = sdev;
- if (scsi_id->workarounds & SBP2_WORKAROUND_INQUIRY_36)
+ if (force_inquiry_hack ||
+ scsi_id->workarounds & SBP2_BREAKAGE_INQUIRY_HACK) {
sdev->inquiry_len = 36;
+ sdev->skip_ms_page_8 = 1;
+ }
return 0;
}
sdev->use_10_for_rw = 1;
sdev->use_10_for_ms = 1;
- if (sdev->type == TYPE_DISK &&
- scsi_id->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)
- sdev->skip_ms_page_8 = 1;
- if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
+ if ((scsi_id->sbp2_firmware_revision & 0xffff00) == 0x0a2700 &&
+ (scsi_id->ud->model_id == 0x000021 /* gen.4 iPod */ ||
+ scsi_id->ud->model_id == 0x000023 /* iPod mini */ ||
+ scsi_id->ud->model_id == 0x00007e /* iPod Photo */ )) {
+ SBP2_INFO("enabling iPod workaround: decrement disk capacity");
sdev->fix_capacity = 1;
+ }
if (scsi_id->ne->guid_vendor_id == 0x0010b9 && /* Maxtor's OUI */
(sdev->type == TYPE_DISK || sdev->type == TYPE_RBC))
sdev->allow_restart = 1;
{
int ret;
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2_module_init");
/* Module load debug option to force one command at a time (serializing I/O) */
if (serialize_io) {
scsi_driver_template.cmd_per_lun = 1;
}
- if (sbp2_default_workarounds & SBP2_WORKAROUND_128K_MAX_TRANS &&
- (max_sectors * 512) > (128 * 1024))
- max_sectors = 128 * 1024 / 512;
+ /* Set max sectors (module load option). Default is 255 sectors. */
scsi_driver_template.max_sectors = max_sectors;
/* Register our high level driver with 1394 stack */
static void __exit sbp2_module_exit(void)
{
- SBP2_DEBUG_ENTER();
+ SBP2_DEBUG("sbp2_module_exit");
hpsb_unregister_protocol(&sbp2_driver);