OSM header file.

diff -Nru a/drivers/scsi/adp94xx/adp94xx_osm.h b/drivers/scsi/adp94xx/adp94xx_osm.h
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/adp94xx/adp94xx_osm.h 2005-02-16 16:08:12 -05:00
@@ -0,0 +1,1375 @@
+/*
+ * Adaptec ADP94xx SAS HBA device driver for Linux. + *
+ * Written by : David Chaw <[EMAIL PROTECTED]>
+ * + * Copyright (c) 2004 Adaptec Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $Id: //depot/razor/linux/src/adp94xx_osm.h#143 $
+ * + */
+
+#ifndef ADP94XX_OSM_H
+#define ADP94XX_OSM_H
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/smp_lock.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/config.h>
+#include <linux/slab.h>
+#include <linux/nmi.h>
+#include <linux/hdreg.h>
+#include <asm/uaccess.h>
+#include <linux/ioctl.h>
+#include <linux/init.h>
+
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(x,y,z) (((x)<<16) + ((y)<<8) + (z))
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#include <linux/blk.h>
+#include "sd.h"
+#endif
+#include <linux/blkdev.h>
+
+#include "scsi.h"
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#include "hosts.h"
+#else
+#include <scsi/scsi_host.h>
+#endif
+
+#define __packed __attribute__ ((packed))
+
+/* Driver name */
+#define ASD_DRIVER_NAME "adp94xx"
+#define ASD_DRIVER_DESCRIPTION "Adaptec Linux SAS/SATA Family Driver"
+#define ASD_DRIVER_VERSION "1.0.5"
+#define ASD_RELEASE_VERSION 12
+
+/* For now, let's limit ourselves on kernel 2.4, 2.6 and greater */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+#error "This driver only support kernel 2.4 or greater"
+#endif
+
+/************************* Forward Declarations *******************************/
+struct asd_softc;
+struct asd_port;
+struct scb;
+struct asd_scb_platform_data; +struct asd_domain;
+struct asd_done_list;
+
+/********************* Definitions Required by the Core ***********************/
+/*
+ * Number of SG segments we require. So long as the S/G segments for
+ * a particular transaction are allocated in a physically contiguous
+ * manner, the number of S/G segments is unrestricted.
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+/*
+ * We dynamically adjust the number of segments in pre-2.5 kernels to
+ * avoid fragmentation issues in the SCSI mid-layer's private memory
+ * allocator. See adp94xx_osm.c asd_size_nseg() for details.
+ */
+extern u_int asd_nseg;
+#define ASD_NSEG asd_nseg
+#define ASD_LINUX_MIN_NSEG 64
+#else
+#define ASD_NSEG 128
+#endif
+
+/* Constants definition */
+#define ASD_MAX_QUEUE ASD_MAX_ALLOCATED_SCBS
+
+/*
+ * DC: Does MAX_SECTORS 255 works for some SATA drives ?
+ * Preferable set it to 255 for better performance in 2.6 kernel.
+ * In 2.4 kernel, it seems that block layer always limited to 64 sectors.
+ */ +//#define ASD_MAX_SECTORS 8192
+#define ASD_MAX_SECTORS 128
+#define ASD_MAX_IO_HANDLES 6
+
+/* Device mapping definition */
+/*
+ * XXX This should really be limited by SAS/SAM. With
+ * the use of hash tables in the domain and target
+ * structures as well as DDB site recycling, we
+ * should have no limit.
+ */
+#define ASD_MAX_LUNS 128
+#define SAS_LUN_LEN 8
+
+/********************************** Misc Macros *******************************/
+#ifndef roundup
+#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
+#endif
+
+static inline uint32_t
+roundup_pow2(uint32_t val)
+{
+ val--;
+ val |= val >> 1;
+ val |= val >> 2;
+ val |= val >> 4;
+ val |= val >> 8;
+ val |= val >> 16;
+ return (val + 1);
+}
+
+#ifndef powerof2
+#define powerof2(x) ((((x)-1)&(x))==0)
+#endif
+
+#ifndef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifndef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#define NUM_ELEMENTS(array) (sizeof(array) / sizeof(*array))
+
+/******************************* Byte Order ***********************************/
+#define asd_htobe16(x) cpu_to_be16(x)
+#define asd_htobe32(x) cpu_to_be32(x)
+#define asd_htobe64(x) cpu_to_be64(x)
+#define asd_htole16(x) cpu_to_le16(x)
+#define asd_htole32(x) cpu_to_le32(x)
+#define asd_htole64(x) cpu_to_le64(x)
+
+#define asd_be16toh(x) be16_to_cpu(x)
+#define asd_be32toh(x) be32_to_cpu(x)
+#define asd_be64toh(x) be64_to_cpu(x)
+#define asd_le16toh(x) le16_to_cpu(x)
+#define asd_le32toh(x) le32_to_cpu(x)
+#define asd_le64toh(x) le64_to_cpu(x)
+
+#ifndef LITTLE_ENDIAN
+#define LITTLE_ENDIAN 1234
+#endif
+
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN 4321
+#endif
+
+#ifndef BYTE_ORDER
+#if defined(__BIG_ENDIAN)
+#define BYTE_ORDER BIG_ENDIAN
+#endif
+#if defined(__LITTLE_ENDIAN)
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif
+#endif /* BYTE_ORDER */
+
+/***************************** Bus Space/DMA **********************************/
+
+struct asd_dma_tag
+{
+ uint32_t alignment;
+ uint32_t maxsize;
+};
+typedef struct asd_dma_tag *bus_dma_tag_t;
+
+struct asd_dmamap
+{
+ dma_addr_t bus_addr;
+};
+typedef struct asd_dmamap * bus_dmamap_t;
+
+/*
+ * Data structure used to track a slab of DMA
+ * safe memory.
+ */
+struct map_node {
+ bus_dmamap_t dmamap;
+ dma_addr_t busaddr;
+ uint8_t *vaddr;
+ struct list_head links;
+};
+
+int asd_dma_tag_create(struct asd_softc *, uint32_t /*alignment*/,
+ uint32_t /*maxsize*/, int /*flags*/,
+ bus_dma_tag_t * /*dma_tagp*/);
+void asd_dma_tag_destroy(struct asd_softc *, bus_dma_tag_t /*tag*/);
+int asd_dmamem_alloc(struct asd_softc *, bus_dma_tag_t /*dmat*/,
+ void** /*vaddr*/, int /*flags*/,
+ bus_dmamap_t * /*mapp*/, dma_addr_t * /*baddr*/);
+void asd_dmamem_free(struct asd_softc *, bus_dma_tag_t /*dmat*/,
+ void* /*vaddr*/, bus_dmamap_t /*map*/);
+void asd_dmamap_destroy(struct asd_softc *, bus_dma_tag_t /*tag*/,
+ bus_dmamap_t /*map*/);
+int asd_alloc_dma_mem(struct asd_softc *, unsigned, void **,
+ dma_addr_t *, bus_dma_tag_t *, struct map_node *);
+void asd_free_dma_mem(struct asd_softc *, bus_dma_tag_t, struct map_node *);
+
+/* IOCTL registration wrappers */
+int asd_register_ioctl_dev(void);
+int asd_unregister_ioctl_dev(void);
+int asd_ctl_init_internal_data(struct asd_softc *asd);
+struct asd_softc * asd_get_softc_by_hba_index(uint32_t hba_index);
+int asd_get_number_of_hbas_present(void);
+struct asd_target * + asd_get_os_target_from_port(struct asd_softc *asd,
+ struct asd_port *port,
+ struct asd_domain *dm);
+struct asd_device *
+ asd_get_device_from_lun(struct asd_softc *asd, + struct asd_target *targ, uint8_t *saslun);
+int asd_get_os_platform_map_from_sasaddr(struct asd_softc *asd, + struct asd_port *port,
+ uint8_t *sasaddr, uint8_t *saslun, + uint8_t *host, uint8_t *bus, + uint8_t *target, uint8_t *lun);
+struct asd_port *
+ asd_get_sas_addr_from_platform_map(struct asd_softc *asd, + uint8_t host, uint8_t bus, + uint8_t target, uint8_t lun, + uint8_t *sasaddr, uint8_t *saslun);
+struct asd_target * + asd_get_sas_target_from_sasaddr(struct asd_softc *asd, + struct asd_port *port, + uint8_t *sasaddr);
+struct asd_target * + asd_get_os_target_from_sasaddr(struct asd_softc *asd, + struct asd_domain *dm, + uint8_t *sasddr);
+struct scb *
+ asd_find_pending_scb_by_qtag(struct asd_softc *asd, uint32_t qtag);
+
+int asd_hwi_check_cmd_pending(struct asd_softc *asd, struct scb *scb, + struct asd_done_list *dl);
+
+/* indicates that the scsi_cmnd is generated by CSMI */
+#define ASD_CSMI_COMMAND 0xfaceface
+
+#if (BITS_PER_LONG > 32) || \
+ (defined CONFIG_HIGHMEM64G && defined CONFIG_HIGHIO)
+ #define ASD_DMA_64BIT_SUPPORT 1
+#else
+ #define ASD_DMA_64BIT_SUPPORT 0
+#endif +
+/*************************** Linux DMA Wrappers *******************************/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#define asd_alloc_coherent(asd, size, bus_addr_ptr) \
+ dma_alloc_coherent(asd->dev, size, bus_addr_ptr, /*flag*/0)
+
+#define asd_free_coherent(asd, size, vaddr, bus_addr) \
+ dma_free_coherent(asd->dev, size, vaddr, bus_addr)
+
+#define asd_map_single(asd, buf, size, direction) \
+ dma_map_single(asd->dev, buf, size, direction)
+
+#define asd_unmap_single(asd, busaddr, size, direction) \
+ dma_unmap_single(asd->dev, busaddr, size, direction)
+
+#define asd_map_sg(asd, sg_list, num_sg, direction) \
+ dma_map_sg(asd->dev, sg_list, num_sg, direction)
+
+#define asd_unmap_sg(asd, sg_list, num_sg, direction) \
+ dma_unmap_sg(asd->dev, sg_list, num_sg, direction)
+
+#else /* LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) */
+
+#define asd_alloc_coherent(asd, size, bus_addr_ptr) \
+ pci_alloc_consistent(asd->dev, size, bus_addr_ptr)
+
+#define asd_free_coherent(asd, size, vaddr, bus_addr) \
+ pci_free_consistent(asd->dev, size, vaddr, bus_addr)
+
+#define asd_map_single(asd, buf, size, direction) \
+ pci_map_single(asd->dev, buf, size, direction)
+
+#define asd_unmap_single(asd, busaddr, size, direction) \
+ pci_unmap_single(asd->dev, busaddr, size, direction)
+
+#define asd_map_sg(asd, sg_list, num_sg, direction) \
+ pci_map_sg(asd->dev, sg_list, num_sg, direction)
+
+#define asd_unmap_sg(asd, sg_list, num_sg, direction) \
+ pci_unmap_sg(asd->dev, sg_list, num_sg, direction)
+#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+
+#define asd_set_dma_mask(asd, mask) dma_set_mask(asd->dev, mask)
+#define asd_set_consistent_dma_mask(asd, mask) \
+ pci_set_consistent_dma_mask(asd_dev_to_pdev(asd->dev), mask)
+
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3)
+
+/*
+ * Device softc is NULL for EISA devices.
+ */
+#define asd_set_dma_mask(asd, mask) \
+ ((asd)->dev == NULL ? 0 : pci_set_dma_mask(asd->dev, mask))
+
+/* Always successfull in 2.4.X kernels */
+#define asd_set_consistent_dma_mask(asd, mask) (0)
+
+#else
+/*
+ * Device softc is NULL for EISA devices.
+ * Always "return" 0 for success.
+ */
+#define asd_set_dma_mask(asd, mask) \
+ (((asd)->dev == NULL) \
+ ? 0 \
+ : (((asd)->dev->dma_mask = mask) && 0))
+
+/* Always successfull in 2.4.X kernels */
+#define asd_set_consistent_dma_mask(asd, mask) (0)
+
+#endif
+
+/* Forward compatibility */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+typedef struct device *asd_dev_t;
+#else
+typedef struct pci_dev *asd_dev_t;
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#define asd_dev_to_pdev(dev) to_pci_dev(dev)
+#define asd_pdev_to_dev(pdev) (&pdev->dev)
+#else
+#define asd_dev_to_pdev(dev) (dev)
+#define asd_pdev_to_dev(pdev) (pdev)
+#endif
+
+#define asd_pci_dev(asd) asd_dev_to_pdev((asd)->dev)
+
+#define ASD_GET_PADR(addr) ((uint32_t) (addr))
+#if (BITS_PER_LONG > 32)
+#define ASD_GET_PUADR(addr) ((uint32_t) ((addr) >> 32))
+#else
+#define ASD_GET_PUADR(addr) ((uint32_t) (0))
+#endif
+
+typedef enum {
+ ASD_SCB_UP_EH_SEM = 0x01,
+ ASD_TIMEOUT_ACTIVE = 0x02,
+ ASD_RELEASE_SIMQ = 0x04,
+} asd_scb_flags;
+
+/**************************** Front End Queues ********************************/
+/*
+ * Data structure used to cast the Linux struct scsi_cmnd to something
+ * that allows us to use the queue macros. The linux structure has
+ * plenty of space to hold the links fields as required by the queue
+ * macros, but the queue macors require them to have the correct type.
+ */
+struct asd_cmd_internal {
+ /* Area owned by the Linux scsi layer. */
+ uint8_t private[offsetof(struct scsi_cmnd, SCp.Status)];
+ struct list_head links;
+ uint32_t end;
+};
+
+union asd_cmd {
+ struct asd_cmd_internal icmd;
+ struct scsi_cmnd scsi_cmd;
+};
+
+#define acmd_icmd(cmd) ((cmd)->icmd)
+#define acmd_scsi_cmd(cmd) ((cmd)->scsi_cmd)
+#define acmd_links icmd.links
+
+/************************** Razor Architecture Layers ************************/
+/*
+ * The following typedefs define the protocols for each layer of the Razor
+ * architecture.
+ */
+
+/*
+ * The Command Set layer consists of everything having to do with the type
+ * of command that is sent to the target.
+ */
+typedef enum {
+ ASD_COMMAND_SET_UNKNOWN,
+ ASD_COMMAND_SET_SCSI,
+ ASD_COMMAND_SET_ATA,
+ ASD_COMMAND_SET_ATAPI,
+ ASD_COMMAND_SET_SMP
+} COMMAND_SET_TYPE;
+
+/*
+ * The Device Protocol layer are things that are specific to a device, + * regardless of which command set is used. For example, a device using
+ * ASD_DEVICE_PROTOCOL_ATA might use the command set ASD_COMMAND_SET_ATA or
+ * ASD_COMMAND_SET_ATAPI.
+ */
+typedef enum {
+ ASD_DEVICE_PROTOCOL_UNKNOWN,
+ ASD_DEVICE_PROTOCOL_SCSI,
+ ASD_DEVICE_PROTOCOL_ATA,
+ ASD_DEVICE_PROTOCOL_SMP
+} DEVICE_PROTOCOL_TYPE;
+
+/*
+ * The transport layer can be thought of as the frame which is used to send
+ * to a device of type DEVICE_PROTOCOL that supports the COMMAND_SET_TYPE
+ * command set.
+ */
+typedef enum {
+ ASD_TRANSPORT_UNKNOWN,
+ ASD_TRANSPORT_SSP,
+ ASD_TRANSPORT_SMP,
+ ASD_TRANSPORT_STP,
+ ASD_TRANSPORT_ATA
+} TRANSPORT_TYPE;
+
+/* + * The management layer deals with issues of routing.
+ */
+typedef enum {
+ ASD_DEVICE_NONE,
+ ASD_DEVICE_FANOUT_EXPANDER,
+ ASD_DEVICE_EDGE_EXPANDER,
+ ASD_DEVICE_END,
+ ASD_DEVICE_UNKNOWN
+} MANAGEMENT_TYPE;
+
+/*
+ * The link layer refers to the link that is connected to the initiator.
+ */
+typedef enum {
+ ASD_LINK_UNKNOWN,
+ ASD_LINK_SAS,
+ ASD_LINK_SATA,
+ ASD_LINK_GPIO,
+ ASD_LINK_I2C
+} LINK_TYPE;
+
+typedef union asd_cmd *asd_io_ctx_t;
+
+/* Discovery include file */
+#include "adp94xx_discover.h"
+
+/* HWI include file */
+#include "adp94xx_hwi.h"
+
+/*************************** Device Data Structures ***************************/
+/*
+ * A per probed device structure used to deal with some error recovery
+ * scenarios that the Linux mid-layer code just doesn't know how to
+ * handle. The structure allocated for a device only becomes persistent
+ * after a successfully completed inquiry command to the target when
+ * that inquiry data indicates a lun is present.
+ */
+typedef enum {
+ ASD_DEV_UNCONFIGURED = 0x0001,
+ ASD_DEV_FREEZE_TIL_EMPTY = 0x0002, /* Freeze until active is empty */
+ ASD_DEV_TIMER_ACTIVE = 0x0004, /* Our timer is active */
+ ASD_DEV_ON_RUN_LIST = 0x0008, /* Queued to be run later */
+ ASD_DEV_Q_BASIC = 0x0010, /* Allow basic device queuing */
+ ASD_DEV_Q_TAGGED = 0x0020, /* Allow full SCSI2 cmd queueing */
+ ASD_DEV_SLAVE_CONFIGURED = 0x0040, /* Device has been configured. */
+ ASD_DEV_DESTROY_WAS_ACTIVE = 0x0080, /* Device has active IO(s) when
+ the ITNL timer expired. */
+ ASD_DEV_DPC_ACTIVE = 0x0100 /* There is an active DPC task,*/
+} asd_dev_flags;
+
+struct asd_target;
+struct asd_device {
+ struct list_head links;
+ struct list_head busyq;
+ /*
+ * The number of transactions currently queued to the device.
+ */
+ int active;
+ /*
+ * The currently allowed number of transactions that can be queued to
+ * the device. Must be signed for conversion from tagged to untagged
+ * mode where the device may have more than one outstanding active + * transaction.
+ */
+ int openings;
+ /*
+ * A positive count indicates that this device's queue is halted.
+ */
+ u_int qfrozen;
+ /*
+ * Cumulative command counter.
+ */
+ u_long commands_issued;
+ /*
+ * The number of tagged transactions when running at our current + * opening level that have been successfully received by this + * device since the last QUEUE FULL.
+ */
+ u_int tag_success_count;
+#define ASD_TAG_SUCCESS_INTERVAL 50
+
+ asd_dev_flags flags;
+ /*
+ * Per device timer and task.
+ */
+ struct timer_list timer;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,41)
+ struct tq_struct taskq;
+#else
+ struct work_struct workq;
+#endif
+ /*
+ * The high limit for the tags variable.
+ */
+ u_int maxtags;
+ /*
+ * The computed number of tags outstanding
+ * at the time of the last QUEUE FULL event.
+ */
+ u_int tags_on_last_queuefull;
+ /*
+ * How many times we have seen a queue full with the same + * number of tags. This is used to stop our adaptive queue depth + * algorithm on devices with a fixed number of tags.
+ */
+ u_int last_queuefull_same_count;
+#define ASD_LOCK_TAGS_COUNT 50
+
+ /* + * Device mapping path for the OS.
+ * This is a duplicate of info in scsi_device and
+ * should be discarded soon.
+ */
+ u_int ch;
+ u_int id;
+ u_int lun;
+ uint8_t saslun[SAS_LUN_LEN];
+ Scsi_Device *scsi_device;
+ struct asd_target *target;
+#ifdef MULTIPATH_IO
+ struct asd_target *current_target;
+#endif
+};
+
+typedef enum {
+ ASD_TARG_FLAGS_NONE = 0x0000,
+ ASD_TARG_IN_RECOVERY = 0x0001,
+ ASD_TARG_ONLINE = 0x0002,
+ ASD_TARG_RESEEN = 0x0004,
+ ASD_TARG_HOT_REMOVED = 0x0008,
+ ASD_TARG_HOT_ADDED = 0x0010,
+ ASD_TARG_NEEDS_MAP = 0x0020,
+ ASD_TARG_MAPPED = 0x0040,
+ ASD_TARG_MAP_BOOT = 0x0080
+} asd_targ_flags;
+
+/* + * Contains pertinent fields needed to generete a hardware DDB.
+ */ +struct asd_ddb_data {
+ uint8_t sas_addr[SAS_ADDR_LEN];
+ uint8_t hashed_sas_addr[HASHED_SAS_ADDR_LEN];
+ uint8_t conn_rate;
+ uint16_t itnl_const;
+ /* Index to DDB entry. */
+ uint16_t conn_handle;
+ uint16_t sister_ddb;
+ /*
+ * Indicates whether the device port protocol is SSP, STP, SMP, + * SATA direct attched or SATA Port Multi. This will be used when
+ * setting value for OPEN field.
+ */ + uint8_t attr;
+ /*
+ * OPEN bit will be set if the device port is connected by
+ * SSP, STP or SMP. In addition for STP, SUPPORT AFFILIATION and + * STP AFFLIATION policy need to be set. + * Otherwise, for SATA direct attached or SATA Port Multi, OPEN bit
+ * shall not be set. + */ + uint8_t open_affl;
+ /*
+ * Initial FIS status.
+ */
+ uint8_t sata_status;
+};
+
+#define FIS_LENGTH 20
+
+/*
+ * Defines for the features_state member
+ */
+#define SATA_USES_DMA 0x0001
+#define SATA_USES_48BIT 0x0002
+#define SATA_USES_QUEUEING 0x0004
+#define SATA_USES_WRITE_FUA 0x0008
+#define SATA_USES_REMOVABLE 0x0010
+#define SATA_USES_WRITE_BUFFER 0x0020
+#define SATA_USES_READ_BUFFER 0x0040
+#define SATA_USES_WRITE_CACHE 0x0080
+#define SATA_USES_READ_AHEAD 0x0100
+#define SATA_USES_SMART 0x0200
+#define SATA_USES_UDMA 0x0400
+
+/*
+ * Defines for the features_enabled member
+ */
+#define WRITE_CACHE_FEATURE_ENABLED 0x0001
+#define READ_AHEAD_FEATURE_ENABLED 0x0002
+#define SMART_FEATURE_ENABLED 0x0004
+#define NEEDS_XFER_SETFEATURES 0x0008
+
+int
+asd_sata_identify_build(
+struct asd_softc *asd,
+struct asd_target *target,
+struct scb *scb
+);
+
+// ----------------------------------------------------------------------------
+
+/*
+ * For devices supporting the SCSI command set
+ */
+struct asd_scsi_command_set {
+ unsigned num_luns;
+ uint32_t flags;
+ uint64_t *luns;
+ uint8_t *ident;
+ unsigned ident_len;
+ uint8_t *inquiry;
+};
+
+struct asd_smp_command_set {
+ struct SMPResponseReportManufacturerInfo
+ manufacturer_info;
+};
+
+/*
+ * For devices supporting the ATA command set
+ */
+struct asd_ata_command_set {
+ /*
+ * There are a few differences in the structures for the data that
+ * is returned by IDENTIFY and PACKET IDENTIFY. We are using the
+ * same structure for both ATA and ATAPI.
+ */
+ struct hd_driveid adp_hd_driveid;
+
+ /*
+ * These members are in the command set structure because they are
+ * deriviced by, or control features and functions specified in the
+ * adp_hd_driveid struture.
+ */
+ unsigned features_state;
+ unsigned features_enabled;
+ unsigned dma_mode_level;
+};
+
+/*
+ * For devices supporting the ATAPI command set
+ */
+struct asd_atapi_command_set {
+ /*
+ * There are a few differences in the structures for the data that
+ * is returned by IDENTIFY and PACKET IDENTIFY. We are using the
+ * same structure for both ATA and ATAPI.
+ */
+ struct hd_driveid adp_hd_driveid;
+
+ /*
+ * These members are in the command set structure because they are
+ * deriviced by, or control features and functions specified in the
+ * adp_hd_driveid struture.
+ */
+ unsigned features_state;
+ unsigned features_enabled;
+ unsigned dma_mode_level;
+};
+
+/*
+ * These are members that are specific to a specific type of command set.
+ */
+union asd_command_set {
+ struct asd_scsi_command_set scsi_command_set;
+ struct asd_ata_command_set ata_command_set;
+ struct asd_atapi_command_set atapi_command_set;
+ struct asd_smp_command_set smp_command_set;
+};
+
+#define ata_cmdset command_set.ata_command_set
+#define scsi_cmdset command_set.scsi_command_set
+#define atapi_cmdset command_set.atapi_command_set
+#define smp_cmdset command_set.smp_command_set
+
+
+// ----------------------------------------------------------------------------
+
+struct asd_ata_device_protocol {
+ uint8_t initial_fis[FIS_LENGTH];
+};
+
+union asd_device_protocol {
+ struct asd_ata_device_protocol ata_device_protocol;
+};
+
+/*
+ * Defines for the menagement_flags member
+ */
+#define DEVICE_SET_ROOT 0x0001
+
+struct asd_target {
+ /*
+ * A positive count indicates that this
+ * target's queue is halted.
+ */
+ u_int qfrozen;
+
+ /*
+ * XXX Use hash table for sparse 8byte lun support???
+ */
+ struct asd_device *devices[ASD_MAX_LUNS];
+ u_int target;
+ int refcount;
+ struct asd_softc *softc;
+ asd_targ_flags flags;
+ struct asd_domain *domain;
+
+ /*
+ * Per target timer.
+ */
+ struct timer_list timer;
+
+ /*
+ * Command Set Layer (SCSI, ATAPI, ATA, SMP)
+ * --------------------------------------------------------
+ */
+ COMMAND_SET_TYPE command_set_type;
+ union asd_command_set command_set;
+
+ /*
+ * Device Protocol Layer (SCSI, ATA, SMP)
+ * --------------------------------------------------------
+ */
+ DEVICE_PROTOCOL_TYPE device_protocol_type;
+ union asd_device_protocol device_protocol;
+
+ /*
+ * Transport Layer (SSP, SMP, STP, FIS)
+ * --------------------------------------------------------
+ */
+ TRANSPORT_TYPE transport_type;
+
+ /*
+ * Management Layer (DIRECT, EXPANDER, FANOUT)
+ * --------------------------------------------------------
+ */
+ MANAGEMENT_TYPE management_type;
+ unsigned num_phys;
+ unsigned num_route_indexes;
+ uint16_t *route_indexes;
+ struct SMPResponseDiscover *Phy;
+ uint8_t *RouteTable;
+ uint32_t management_flags;
+
+ /*
+ * Our parent SAS device (e.g. expander)
+ * in this SAS domain.
+ */
+ struct asd_target *parent;
+ /*
+ * Our children SAS devices (if not end device)
+ * in this SAS domain.
+ */
+ struct list_head children;
+ /*
+ * List of targets that are connected to a parent + * expander (children)
+ */
+ struct list_head siblings;
+ /*
+ * List links for chaining together all targets
+ * in this SAS domain on to the port object.
+ */
+ struct list_head all_domain_targets;
+ /*
+ * List links of targets that need to be validated
+ * because they have been hot-added or hot-removed.
+ */
+ struct list_head validate_links; + /*
+ * List links of target structures that map to the
+ * same physical sevice.
+ */
+ struct list_head multipath; +
+ /*
+ * Link Layer (SAS, SATA, GPIO, I2C)
+ * --------------------------------------------------------
+ */
+ LINK_TYPE link_type;
+ struct asd_ddb_data ddb_profile;
+
+ /*
+ * Controller port used to route to
+ * this device.
+ */
+ struct asd_port *src_port;
+};
+
+struct asd_domain {
+ /*
+ * XXX Use Hash table to support
+ * large/sparse target configurations.
+ */
+ struct asd_target *targets[ASD_MAX_TARGETS];
+ u_int channel_mapping;
+ u_int refcount;
+};
+
+typedef enum {
+ ASD_DISCOVERY_ACTIVE = 0x01,
+ ASD_DISCOVERY_INIT = 0x02,
+ ASD_DISCOVERY_SHUTDOWN = 0x04,
+ ASD_RECOVERY_SHUTDOWN = 0x08,
+#ifdef ASD_EH_SIMULATION
+ ASD_EH_SIMUL_SHUTDOWN = 0x10
+#endif
+} asd_platform_flags;
+
+struct asd_scb_platform_data {
+ struct asd_target *targ;
+ struct asd_device *dev;
+ asd_scb_flags flags;
+ dma_addr_t buf_busaddr;
+ /*
+ * Timeout timer tick, used to timeout internal cmd that is + * sent to the sequencer or target.
+ */ + struct timer_list timeout; +};
+
+struct asd_platform_data {
+ spinlock_t spinlock;
+ struct Scsi_Host *scsi_host;
+
+ /*
+ * Channel to Domain Mapping.
+ */
+ struct asd_domain **domains;
+ u_int num_domains;
+
+ /*
+ * Queued device I/O scheduling support.
+ */
+ struct list_head pending_os_scbs;
+ struct list_head device_runq;
+ struct tasklet_struct runq_tasklet;
+ struct tasklet_struct unblock_tasklet;
+ u_int qfrozen;
+
+ /*
+ * Completion Ordering Queue.
+ */
+ struct list_head completeq;
+
+ /*
+ * LRU target DDB ageing queue. Used to
+ * select candidates for DDB recycling.
+ * LFU would be a better scheme and could
+ * be achieved in O(logN) using a heap
+ * queue, but keep this simple for now.
+ */
+ struct list_head lru_ddb_q;
+
+ /*
+ * Discovery Thread Support.
+ */
+ pid_t discovery_pid;
+ struct semaphore discovery_sem;
+ struct semaphore discovery_ending_sem;
+
+ /*
+ * Error Recovery Thread Support.
+ */
+ pid_t ehandler_pid;
+ struct semaphore ehandler_sem;
+ struct semaphore ehandler_ending_sem;
+
+#ifdef ASD_EH_SIMULATION
+ /*
+ * EH Recovery Simulation thread.
+ */
+ pid_t eh_simul_pid;
+ struct semaphore eh_simul_sem;
+#endif
+
+ /*
+ * Wait Queue.
+ */
+ wait_queue_head_t waitq;
+
+ /*
+ * Mid-layer error recovery entry point semaphore.
+ */
+ struct semaphore eh_sem;
+ struct semaphore wait_sem;
+
+ asd_platform_flags flags;
+};
+
+/*
+ * Internal data structures.
+ */
+typedef struct asd_init_status {
+ uint8_t asd_notifier_enabled;
+ uint8_t asd_pci_registered;
+ uint8_t asd_irq_registered;
+ uint8_t asd_ioctl_registered;
+ uint8_t asd_init_state;
+} asd_init_status_t;
+
+
+/* SMP Locking mechanism routines */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK))
+#define SCSI_ML_HAS_HOST_LOCK 1
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#define asd_assign_host_lock(asd) \
+ scsi_assign_lock((asd)->platform_data->scsi_host, \
+ &(asd)->platform_data->spinlock)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,21) \
+ && defined(ASD_RED_HAT_LINUX_KERNEL)
+#define asd_assign_host_lock(asd) \
+do { \
+ (asd)->platform_data->scsi_host->host_lock = \
+ &(asd)->platform_data->spinlock; \
+} while (0)
+#else
+#define asd_assign_host_lock(asd) \
+do { \
+ (asd)->platform_data->scsi_host->lock = \
+ &(asd)->platform_data->spinlock; \
+} while (0)
+#endif
+#else /* !SCSI_ML_HAS_HOST_LOCK */
+#define SCSI_ML_HAS_HOST_LOCK 0
+#define asd_assign_host_lock(asd)
+#endif /* !SCSI_ML_HAS_HOST_LOCK */
+
+/* OS utility wrappers */
+#define asd_alloc_mem(size, flags) kmalloc(size, flags)
+#define asd_free_mem(ptr) kfree(ptr)
+ +/* Debug Logging macro */
+
+#define ASD_DBG_INIT 0x01
+#define ASD_DBG_INFO 0x02
+#define ASD_DBG_RUNTIME 0x10
+#define ASD_DBG_ISR 0x20
+#define ASD_DBG_ERROR 0x40
+
+
+/* Debug mask to control the Debug Level printout. */
+extern u_int debug_mask;
+
+#ifdef ASD_DEBUG
+
+#define asd_log(debug_level, fmt, args...) \
+do { \
+ if ((debug_level & debug_mask) != 0) { \
+ printk("%s(%d) : ", __FUNCTION__, __LINE__); \
+ printk(fmt, ##args); \
+ } \
+} while (0)
+
+/* For initial debugging purpose only. */
+#define IN 0
+#define OUT 1
+#define LINE 2
+
+#define ASD_DBG_FUNC(x) \
+do { \
+ if (x == IN) { \
+ printk("+++ Entering Function: %s:%d.\n", __FUNCTION__, \
+ __LINE__); \
+ } else if (x == OUT) { \
+ printk("--- Exiting Function: %s:%d.\n", __FUNCTION__, \
+ __LINE__); \
+ } else { \
+ printk("*** %s (%d).\n", __FUNCTION__, __LINE__); \
+ } \
+} while (0)
+
+#if KDB_ENABLE
+#define ASSERT(expression) \
+ if (!(expression)) { \
+ printk("assertion failed: %s, file: %s, line: %d\n", \
+ #expression, __FILE__, __LINE__); \
+ KDB_ENTER(); \
+ }
+#else
+#define ASSERT(expression) \
+ if (!(expression)) { \
+ panic("assertion failed: %s, file: %s, line: %d\n", \
+ #expression, __FILE__, __LINE__); \
+ }
+#endif
+
+#else
+
+#define asd_log(debug_level, fmt, args...) /**/
+#define ASD_DBG_FUNC(x) /**/
+
+#define ASSERT(expression)
+
+#endif /* ASD_DEBUG */ +
+#define asd_print(fmt, args...) printk(fmt, ##args)
+
+#define ASD_DUMP_REG(reg) /**/
+
+#ifndef IRQ_RETVAL
+typedef void irqreturn_t;
+#define IRQ_RETVAL(x) /**/
+#endif
+
+/*
+ * SCSI Status Byte
+ */
+#define SCSI_STATUS_OK 0x00
+#define SCSI_STATUS_CHECK_COND 0x02
+#define SCSI_STATUS_COND_MET 0x04
+#define SCSI_STATUS_BUSY 0x08
+#define SCSI_STATUS_INTERMED 0x10
+#define SCSI_STATUS_INTERMED_COND_MET 0x14
+#define SCSI_STATUS_RESERV_CONFLICT 0x18
+#define SCSI_STATUS_CMD_TERMINATED 0x22 /* Obsolete in SAM-2 */
+#define SCSI_STATUS_QUEUE_FULL 0x28
+#define SCSI_STATUS_ACA_ACTIVE 0x30
+#define SCSI_STATUS_TASK_ABORTED 0x40
+
+struct scsi_sense_data
+{
+ uint8_t error_code;
+#define SSD_ERRCODE 0x7F
+#define SSD_CURRENT_ERROR 0x70
+#define SSD_DEFERRED_ERROR 0x71
+#define SSD_ERRCODE_VALID 0x80
+ uint8_t segment;
+ uint8_t flags;
+#define SSD_KEY 0x0F
+#define SSD_KEY_NO_SENSE 0x00
+#define SSD_KEY_RECOVERED_ERROR 0x01
+#define SSD_KEY_NOT_READY 0x02
+#define SSD_KEY_MEDIUM_ERROR 0x03
+#define SSD_KEY_HARDWARE_ERROR 0x04
+#define SSD_KEY_ILLEGAL_REQUEST 0x05
+#define SSD_KEY_UNIT_ATTENTION 0x06
+#define SSD_KEY_DATA_PROTECT 0x07
+#define SSD_KEY_BLANK_CHECK 0x08
+#define SSD_KEY_Vendor_Specific 0x09
+#define SSD_KEY_COPY_ABORTED 0x0a
+#define SSD_KEY_ABORTED_COMMAND 0x0b
+#define SSD_KEY_EQUAL 0x0c
+#define SSD_KEY_VOLUME_OVERFLOW 0x0d
+#define SSD_KEY_MISCOMPARE 0x0e
+#define SSD_KEY_RESERVED 0x0f
+#define SSD_ILI 0x20
+#define SSD_EOM 0x40
+#define SSD_FILEMARK 0x80
+ uint8_t info[4];
+ uint8_t extra_len;
+ uint8_t cmd_spec_info[4];
+ uint8_t add_sense_code;
+ uint8_t add_sense_code_qual;
+ uint8_t fru;
+ uint8_t sense_key_spec[3];
+#define SSD_SCS_VALID 0x80
+#define SSD_FIELDPTR_CMD 0x40
+#define SSD_BITPTR_VALID 0x08
+#define SSD_BITPTR_VALUE 0x07
+#define SSD_MIN_SIZE 18
+ uint8_t extra_bytes[14];
+#define SSD_FULL_SIZE sizeof(struct scsi_sense_data)
+};
+
+static inline void scsi_ulto2b(uint32_t val, uint8_t *bytes);
+static inline void scsi_ulto3b(uint32_t val, uint8_t *bytes);
+static inline void scsi_ulto4b(uint32_t val, uint8_t *bytes);
+static inline uint32_t scsi_2btoul(uint8_t *bytes);
+static inline uint32_t scsi_3btoul(uint8_t *bytes);
+static inline int32_t scsi_3btol(uint8_t *bytes);
+static inline uint32_t scsi_4btoul(uint8_t *bytes);
+
+static inline void
+scsi_ulto2b(uint32_t val, uint8_t *bytes)
+{
+ bytes[0] = (val >> 8) & 0xff;
+ bytes[1] = val & 0xff;
+}
+
+static inline void
+scsi_ulto3b(uint32_t val, uint8_t *bytes)
+{
+ bytes[0] = (val >> 16) & 0xff;
+ bytes[1] = (val >> 8) & 0xff;
+ bytes[2] = val & 0xff;
+}
+
+static inline void
+scsi_ulto4b(uint32_t val, uint8_t *bytes)
+{
+ bytes[0] = (val >> 24) & 0xff;
+ bytes[1] = (val >> 16) & 0xff;
+ bytes[2] = (val >> 8) & 0xff;
+ bytes[3] = val & 0xff;
+}
+
+static inline uint32_t
+scsi_2btoul(uint8_t *bytes)
+{
+ uint32_t rv;
+
+ rv = (bytes[0] << 8) |
+ bytes[1];
+ return (rv);
+}
+
+static inline uint32_t
+scsi_3btoul(uint8_t *bytes)
+{
+ uint32_t rv;
+
+ rv = (bytes[0] << 16) |
+ (bytes[1] << 8) |
+ bytes[2];
+ return (rv);
+}
+
+static inline int32_t +scsi_3btol(uint8_t *bytes)
+{
+ uint32_t rc = scsi_3btoul(bytes);
+ + if (rc & 0x00800000)
+ rc |= 0xff000000;
+
+ return (int32_t) rc;
+}
+
+static inline uint32_t
+scsi_4btoul(uint8_t *bytes)
+{
+ uint32_t rv;
+
+ rv = (bytes[0] << 24) |
+ (bytes[1] << 16) |
+ (bytes[2] << 8) |
+ bytes[3];
+ return (rv);
+}
+
+/*********************** Transaction Access Wrappers **************************/
+static inline void asd_cmd_set_host_status(Scsi_Cmnd *cmd, u_int);
+static inline void asd_cmd_set_scsi_status(Scsi_Cmnd *cmd, u_int);
+static inline uint32_t asd_cmd_get_host_status(Scsi_Cmnd *cmd);
+static inline uint32_t asd_cmd_get_scsi_status(Scsi_Cmnd *cmd);
+static inline void asd_freeze_scb(struct scb *scb);
+static inline void asd_unfreeze_scb(struct scb *scb);
+
+#define CMD_DRIVER_STATUS_MASK 0xFF000000
+#define CMD_DRIVER_STATUS_SHIFT 24
+#define CMD_HOST_STATUS_MASK 0x00FF0000
+#define CMD_HOST_STATUS_SHIFT 16
+#define CMD_MSG_STATUS_MASK 0x0000FF00
+#define CMD_MSG_STATUS_SHIFT 8
+#define CMD_SCSI_STATUS_MASK 0x000000FF
+#define CMD_SCSI_STATUS_SHIFT 0
+#define CMD_REQ_INPROG 0xFF
+
+static inline
+void asd_cmd_set_driver_status(Scsi_Cmnd *cmd, u_int status)
+{
+ cmd->result &= ~CMD_DRIVER_STATUS_MASK;
+ cmd->result |= status << CMD_DRIVER_STATUS_SHIFT;
+}
+
+static inline
+void asd_cmd_set_host_status(Scsi_Cmnd *cmd, u_int status)
+{
+ cmd->result &= ~CMD_HOST_STATUS_MASK;
+ cmd->result |= status << CMD_HOST_STATUS_SHIFT;
+}
+
+static inline
+void asd_cmd_set_scsi_status(Scsi_Cmnd *cmd, u_int status)
+{
+ cmd->result &= ~CMD_SCSI_STATUS_MASK;
+ cmd->result |= status;
+}
+
+static inline
+uint32_t asd_cmd_get_host_status(Scsi_Cmnd *cmd)
+{
+ return ((cmd->result & CMD_HOST_STATUS_MASK) >> CMD_HOST_STATUS_SHIFT);
+}
+
+static inline
+uint32_t asd_cmd_get_scsi_status(Scsi_Cmnd *cmd)
+{
+ return ((cmd->result & CMD_SCSI_STATUS_MASK) >> CMD_SCSI_STATUS_SHIFT);
+}
+
+static inline void
+asd_freeze_scb(struct scb *scb)
+{
+ if ((scb->flags & SCB_DEV_QFRZN) == 0) {
+ scb->flags |= SCB_DEV_QFRZN;
+ scb->platform_data->dev->qfrozen++;
+ }
+}
+
+static inline void
+asd_unfreeze_scb(struct scb *scb)
+{
+ if ((scb->flags & SCB_DEV_QFRZN) != 0) {
+ scb->flags &= ~SCB_DEV_QFRZN;
+ scb->platform_data->dev->qfrozen--;
+ }
+}
+
+// TODO - where is right spot for these???
+typedef enum {
+ ASD_COMMAND_BUILD_OK,
+ ASD_COMMAND_BUILD_FAILED,
+ ASD_COMMAND_BUILD_FINISHED
+} ASD_COMMAND_BUILD_STATUS;
+
+ASD_COMMAND_BUILD_STATUS + asd_setup_data(struct asd_softc *asd, struct scb *scb, Scsi_Cmnd *cmd);
+
+DISCOVER_RESULTS
+ asd_do_discovery(struct asd_softc *asd, struct asd_port *port);
+
+DISCOVER_RESULTS
+ asd_run_state_machine(struct state_machine_context *sm_contextp);
+
+int asd_platform_alloc(struct asd_softc *asd);
+void asd_platform_free(struct asd_softc *asd);
+
+struct asd_scb_platform_data *
+ asd_alloc_scb_platform_data(struct asd_softc *asd);
+void asd_free_scb_platform_data(struct asd_softc *asd,
+ struct asd_scb_platform_data *pdata);
+void asd_unmap_scb(struct asd_softc *asd, struct scb *scb);
+void asd_recover_cmds(struct asd_softc *asd);
+void asd_hwi_release_sata_spinup_hold(struct asd_softc *asd,
+ struct asd_phy *phy);
+
+struct asd_target *
+ asd_alloc_target(struct asd_softc *asd, struct asd_port *src_port);
+void asd_free_target(struct asd_softc *asd, struct asd_target *targ);
+int asd_map_target(struct asd_softc *asd, struct asd_target *targ);
+
+struct asd_device *
+ asd_alloc_device(struct asd_softc *asd, struct asd_target *targ, + u_int ch, u_int id, u_int lun);
+void asd_free_device(struct asd_softc *asd, struct asd_device *dev);
+struct asd_device *
+ asd_get_device(struct asd_softc *asd, u_int ch, u_int id,
+ u_int lun, int alloc);
+void asd_remap_device(struct asd_softc *asd, struct asd_target *target,
+ struct asd_target *multipath_target);
+void asd_timed_run_dev_queue(u_long arg);
+void asd_destroy_device(void *arg);
+
+#ifndef list_for_each_entry_safe
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against + * removal of list entry
+ * @pos: the type * to use as a loop counter.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+#endif
+
+#ifndef list_for_each_entry
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ prefetch(pos->member.next); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member), \
+ prefetch(pos->member.next))
+
+#endif
+
+#define list_move_all(to_list, from_list) \
+ if (!list_empty(from_list)) { \
+ (to_list)->next = (from_list)->next; \
+ (to_list)->prev = (from_list)->prev; \
+ (from_list)->next->prev = to_list; \
+ (from_list)->prev->next = to_list; \
+ INIT_LIST_HEAD(from_list); \
+ } else { \
+ INIT_LIST_HEAD(to_list); \
+ }
+
+#define list_copy(to_list, from_list) \
+do { \
+ (to_list)->next = (from_list)->next; \
+ (to_list)->prev = (from_list)->prev; \
+} while (0)
+
+#endif /* ADP94XX_OSM_H */


-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to