📄 sbp2.c
字号:
/* * sbp2.c - SBP-2 protocol driver for IEEE-1394 * * Copyright (C) 2000 James Goodwin, Filanet Corporation (www.filanet.com) * jamesg@filanet.com (JSG) * * Copyright (C) 2003 Ben Collins <bcollins@debian.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* * Brief Description: * * This driver implements the Serial Bus Protocol 2 (SBP-2) over IEEE-1394 * under Linux. The SBP-2 driver is implemented as an IEEE-1394 high-level * driver. It also registers as a SCSI lower-level driver in order to accept * SCSI commands for transport using SBP-2. * * You may access any attached SBP-2 (usually storage devices) as regular * SCSI devices. E.g. mount /dev/sda1, fdisk, mkfs, etc.. * * See http://www.t10.org/drafts.htm#sbp2 for the final draft of the SBP-2 * specification and for where to purchase the official standard. * * TODO: * - look into possible improvements of the SCSI error handlers * - handle Unit_Characteristics.mgt_ORB_timeout and .ORB_size * - handle Logical_Unit_Number.ordered * - handle src == 1 in status blocks * - reimplement the DMA mapping in absence of physical DMA so that * bus_to_virt is no longer required * - debug the handling of absent physical DMA * - replace CONFIG_IEEE1394_SBP2_PHYS_DMA by automatic detection * (this is easy but depends on the previous two TODO items) * - make the parameter serialize_io configurable per device * - move all requests to fetch agent registers into non-atomic context, * replace all usages of sbp2util_node_write_no_wait by true transactions * Grep for inline FIXME comments below. */#include <linux/compiler.h>#include <linux/delay.h>#include <linux/device.h>#include <linux/dma-mapping.h>#include <linux/gfp.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/list.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/slab.h>#include <linux/spinlock.h>#include <linux/stat.h>#include <linux/string.h>#include <linux/stringify.h>#include <linux/types.h>#include <linux/wait.h>#include <asm/byteorder.h>#include <asm/errno.h>#include <asm/param.h>#include <asm/scatterlist.h>#include <asm/system.h>#include <asm/types.h>#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA#include <asm/io.h> /* for bus_to_virt */#endif#include <scsi/scsi.h>#include <scsi/scsi_cmnd.h>#include <scsi/scsi_dbg.h>#include <scsi/scsi_device.h>#include <scsi/scsi_host.h>#include "csr1212.h"#include "highlevel.h"#include "hosts.h"#include "ieee1394.h"#include "ieee1394_core.h"#include "ieee1394_hotplug.h"#include "ieee1394_transactions.h"#include "ieee1394_types.h"#include "nodemgr.h"#include "sbp2.h"/* * Module load parameter definitions *//* * Change max_speed on module load if you have a bad IEEE-1394 * controller that has trouble running 2KB packets at 400mb. * * NOTE: On certain OHCI parts I have seen short packets on async transmit * (probably due to PCI latency/throughput issues with the part). You can * bump down the speed if you are running into problems. */static int sbp2_max_speed = IEEE1394_SPEED_MAX;module_param_named(max_speed, sbp2_max_speed, int, 0644);MODULE_PARM_DESC(max_speed, "Force max speed " "(3 = 800Mb/s, 2 = 400Mb/s, 1 = 200Mb/s, 0 = 100Mb/s)");/* * Set serialize_io to 1 if you'd like only one scsi command sent * down to us at a time (debugging). This might be necessary for very * badly behaved sbp2 devices. */static int sbp2_serialize_io = 1;module_param_named(serialize_io, sbp2_serialize_io, int, 0444);MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers " "(default = 1, faster = 0)");/* * Bump up max_sectors if you'd like to support very large sized * transfers. Please note that some older sbp2 bridge chips are broken for * transfers greater or equal to 128KB. Default is a value of 255 * sectors, or just under 128KB (at 512 byte sector size). I can note that * the Oxsemi sbp2 chipsets have no problems supporting very large * transfer sizes. */static int sbp2_max_sectors = SBP2_MAX_SECTORS;module_param_named(max_sectors, sbp2_max_sectors, int, 0444);MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported " "(default = " __stringify(SBP2_MAX_SECTORS) ")");/* * Exclusive login to sbp2 device? In most cases, the sbp2 driver should * do an exclusive login, as it's generally unsafe to have two hosts * 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. */static int sbp2_exclusive_login = 1;module_param_named(exclusive_login, sbp2_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. * * - 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. */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)");#define SBP2_INFO(fmt, args...) HPSB_INFO("sbp2: "fmt, ## args)#define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args)/* * Globals */static void sbp2scsi_complete_all_commands(struct sbp2_lu *, u32);static void sbp2scsi_complete_command(struct sbp2_lu *, u32, struct scsi_cmnd *, void (*)(struct scsi_cmnd *));static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *);static int sbp2_start_device(struct sbp2_lu *);static void sbp2_remove_device(struct sbp2_lu *);static int sbp2_login_device(struct sbp2_lu *);static int sbp2_reconnect_device(struct sbp2_lu *);static int sbp2_logout_device(struct sbp2_lu *);static void sbp2_host_reset(struct hpsb_host *);static int sbp2_handle_status_write(struct hpsb_host *, int, int, quadlet_t *, u64, size_t, u16);static int sbp2_agent_reset(struct sbp2_lu *, int);static void sbp2_parse_unit_directory(struct sbp2_lu *, struct unit_directory *);static int sbp2_set_busy_timeout(struct sbp2_lu *);static int sbp2_max_speed_and_size(struct sbp2_lu *);static const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC };static struct hpsb_highlevel sbp2_highlevel = { .name = SBP2_DEVICE_NAME, .host_reset = sbp2_host_reset,};static struct hpsb_address_ops sbp2_ops = { .write = sbp2_handle_status_write};#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMAstatic int sbp2_handle_physdma_write(struct hpsb_host *, int, int, quadlet_t *, u64, size_t, u16);static int sbp2_handle_physdma_read(struct hpsb_host *, int, quadlet_t *, u64, size_t, u16);static struct hpsb_address_ops sbp2_physdma_ops = { .read = sbp2_handle_physdma_read, .write = sbp2_handle_physdma_write,};#endif/* * Interface to driver core and IEEE 1394 core */static struct ieee1394_device_id sbp2_id_table[] = { { .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff, .version = SBP2_SW_VERSION_ENTRY & 0xffffff}, {}};MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table);static int sbp2_probe(struct device *);static int sbp2_remove(struct device *);static int sbp2_update(struct unit_directory *);static struct hpsb_protocol_driver sbp2_driver = { .name = SBP2_DEVICE_NAME, .id_table = sbp2_id_table, .update = sbp2_update, .driver = { .probe = sbp2_probe, .remove = sbp2_remove, },};/* * Interface to SCSI core */static int sbp2scsi_queuecommand(struct scsi_cmnd *, void (*)(struct scsi_cmnd *));static int sbp2scsi_abort(struct scsi_cmnd *);static int sbp2scsi_reset(struct scsi_cmnd *);static int sbp2scsi_slave_alloc(struct scsi_device *);static int sbp2scsi_slave_configure(struct scsi_device *);static void sbp2scsi_slave_destroy(struct scsi_device *);static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *, struct device_attribute *, char *);static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL);static struct device_attribute *sbp2_sysfs_sdev_attrs[] = { &dev_attr_ieee1394_id, NULL};static struct scsi_host_template sbp2_shost_template = { .module = THIS_MODULE, .name = "SBP-2 IEEE-1394", .proc_name = SBP2_DEVICE_NAME, .queuecommand = sbp2scsi_queuecommand, .eh_abort_handler = sbp2scsi_abort, .eh_device_reset_handler = sbp2scsi_reset, .slave_alloc = sbp2scsi_slave_alloc, .slave_configure = sbp2scsi_slave_configure, .slave_destroy = sbp2scsi_slave_destroy, .this_id = -1, .sg_tablesize = SG_ALL, .use_clustering = ENABLE_CLUSTERING, .cmd_per_lun = SBP2_MAX_CMDS, .can_queue = SBP2_MAX_CMDS, .sdev_attrs = sbp2_sysfs_sdev_attrs,};/* for match-all entries in sbp2_workarounds_table */#define SBP2_ROM_VALUE_WILDCARD 0x1000000/* * 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. */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, .model_id = SBP2_ROM_VALUE_WILDCARD, .workarounds = SBP2_WORKAROUND_INQUIRY_36, }, /* Symbios bridge */ { .firmware_revision = 0xa0b800, .model_id = SBP2_ROM_VALUE_WILDCARD, .workarounds = SBP2_WORKAROUND_128K_MAX_TRANS, }, /* 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, }};/************************************** * General utility functions **************************************/#ifndef __BIG_ENDIAN/* * Converts a buffer from be32 to cpu byte ordering. Length is in bytes. */static inline void sbp2util_be32_to_cpu_buffer(void *buffer, int length){ u32 *temp = buffer; for (length = (length >> 2); length--; ) temp[length] = be32_to_cpu(temp[length]);}/* * Converts a buffer from cpu to be32 byte ordering. Length is in bytes. */static inline void sbp2util_cpu_to_be32_buffer(void *buffer, int length){ u32 *temp = buffer; for (length = (length >> 2); length--; ) temp[length] = cpu_to_be32(temp[length]);}#else /* BIG_ENDIAN *//* Why waste the cpu cycles? */#define sbp2util_be32_to_cpu_buffer(x,y) do {} while (0)#define sbp2util_cpu_to_be32_buffer(x,y) do {} while (0)#endifstatic DECLARE_WAIT_QUEUE_HEAD(sbp2_access_wq);/* * Waits for completion of an SBP-2 access request. * Returns nonzero if timed out or prematurely interrupted. */static int sbp2util_access_timeout(struct sbp2_lu *lu, int timeout){ long leftover; leftover = wait_event_interruptible_timeout( sbp2_access_wq, lu->access_complete, timeout); lu->access_complete = 0; return leftover <= 0;}static void sbp2_free_packet(void *packet){ hpsb_free_tlabel(packet); hpsb_free_packet(packet);}/* * This is much like hpsb_node_write(), except it ignores the response * subaction and returns immediately. Can be used from atomic context. */static int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr, quadlet_t *buf, size_t len){ struct hpsb_packet *packet; packet = hpsb_make_writepacket(ne->host, ne->nodeid, addr, buf, len); if (!packet) return -ENOMEM; hpsb_set_packet_complete_task(packet, sbp2_free_packet, packet); hpsb_node_fill_packet(ne, packet); if (hpsb_send_packet(packet) < 0) { sbp2_free_packet(packet); return -EIO; } return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -