/*
* SBP2 driver (SCSI over IEEE1394)
*
* Copyright (C) 2005-2007 Kristian Hoegsberg <krh@bitplanet.net>
*
* 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.
*/
/*
* The basic structure of this driver is based on the old storage driver,
* drivers/ieee1394/sbp2.c, originally written by
* James Goodwin <jamesg@filanet.com>
* with later contributions and ongoing maintenance from
* Ben Collins <bcollins@debian.org>,
* Stefan Richter <stefanr@s5r6.in-berlin.de>
* and many others.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/device.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
#include <linux/blkdev.h>
#include <linux/timer.h>
#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 "fw-transaction.h"
#include "fw-topology.h"
#include "fw-device.h"
/* I don't know why the SCSI stack doesn't define something like this... */
typedef void (*scsi_done_fn_t)(struct scsi_cmnd *);
static const char sbp2_driver_name[] = "sbp2";
struct sbp2_device {
struct kref kref;
struct fw_unit *unit;
struct fw_address_handler address_handler;
struct list_head orb_list;
u64 management_agent_address;
u64 command_block_agent_address;
u32 workarounds;
int login_id;
/*
* We cache these addresses and only update them once we've
* logged in or reconnected to the sbp2 device. That way, any
* IO to the device will automatically fail and get retried if
* it happens in a window where the device is not ready to
* handle it (e.g. after a bus reset but before we reconnect).
*/
int node_id;
int address_high;
int generation;
int retries;
struct delayed_work work;
};
#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
#define SBP2_MAX_SECTORS 255 /* Max sectors supported */
#define SBP2_ORB_TIMEOUT 2000 /* Timeout in ms */
#define SBP2_ORB_NULL 0x80000000
#define SBP2_DIRECTION_TO_MEDIA 0x0
#define SBP2_DIRECTION_FROM_MEDIA 0x1
/* Unit directory keys */
#define SBP2_COMMAND_SET_SPECIFIER 0x38
#define SBP2_COMMAND_SET 0x39
#define SBP2_COMMAND_SET_REVISION 0x3b
#define SBP2_FIRMWARE_REVISION 0x3c
/* Flags for detected oddities and brokeness */
#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1
#define SBP2_WORKAROUND_INQUIRY_36 0x2
#define SBP2_WORKAROUND_MODE_SENSE_8 0x4
#define SBP2_WORKAROUND_FIX_CAPACITY 0x8
#define SBP2_WORKAROUND_OVERRIDE 0x100
/* Management orb opcodes */
#define SBP2_LOGIN_REQUEST 0x0
#define SBP2_QUERY_LOGINS_REQUEST 0x1
#define SBP2_RECONNECT_REQUEST 0x3
#define SBP2_SET_PASSWORD_REQUEST 0x4
#define SBP2_LOGOUT_REQUEST 0x7
#define SBP2_ABORT_TASK_REQUEST 0xb
#define SBP2_ABORT_TASK_SET 0xc
#define SBP2_LOGICAL_UNIT_RESET 0xe
#define SBP2_TARGET_RESET_REQUEST 0xf
/* Offsets for command block agent registers */
#define SBP2_AGENT_STATE 0x00
#define SBP2_AGENT_RESET 0x04
#define SBP2_ORB_POINTER 0x08
#define SBP2_DOORBELL 0x10
#define SBP2_UNSOLICITED_STATUS_ENABLE 0x14
/* Status write response codes */
#define SBP2_STATUS_REQUEST_COMPLETE 0x0
#define SBP2_STATUS_TRANSPORT_FAILURE 0x1
#define SBP2_STATUS_ILLEGAL_REQUEST 0x2
#define SBP2_STATUS_VENDOR_DEPENDENT 0x3
#define STATUS_GET_ORB_HIGH(v) ((v).status & 0xffff)
#define STATUS_GET_SBP_STATUS(v) (((v).status >> 16) & 0xff)
#define STATUS_GET_LEN(v) (((v).status >> 24) & 0x07)
#define STATUS_GET_DEAD(v) (((v).status >> 27) & 0x01)
#define STATUS_GET_RESPONSE(v) (((v).status >> 28) & 0x03)
#define STATUS_GET_SOURCE(v) (((v).status >> 30) & 0x03)
#define STATUS_GET_ORB_LOW(v) ((v).orb_low)
#define STATUS_GET_DATA(v) ((v).data)
struct sbp2_status {
u32 status;
u32 orb_low;
u8 data[24];
};
struct sbp2_pointer {
u32 high;
u32 low;
};
struct sbp2_orb {
struct fw_transaction t;
dma_addr_t request_bus;
int rcode;
struct sbp2_pointer pointer;
void (*callback)(struct sbp2_orb * orb, struct sbp2_status * status);
struct list_head link;
};
#define MANAGEMENT_ORB_LUN(v) ((v))
#define MANAGEMENT_ORB_FUNCTION(v) ((v) << 16)
#define MANAGEMENT_ORB_RECONNECT(v) ((v) << 20)
#define MANAGEMENT_ORB_EXCLUSIVE ((1) << 28)
#define MANAGEMENT_ORB_REQUEST_FORMAT(v) ((v) << 29)
#define MANAGEMENT_ORB_NOTIFY ((1) << 31)
#define MANAGEMENT_ORB_RESPONSE_LENGTH(v) ((v))
#define MANAGEMENT_ORB_PASSWORD_LENGTH(v) ((v) << 16)
struct sbp2_management_orb {
struct sbp2_orb base;
struct {
struct sbp2_pointer password;
struct sbp2_pointer response;
u32 misc;
u32 length;
struct sbp2_pointer status_fifo;
} request;
__be32 response[4];
dma_addr_t response_bus;
struct completion done;
struct sbp2_status status;
};
#define LOGIN_RESPONSE_GET_LOGIN_ID(v) ((v).misc & 0xffff)
#define LOGIN_RESPONSE_GET_LENGTH(v) (((v).misc >> 16) & 0xffff)
struct sbp2_login_response {
u32 misc