#include <linux/types.h>
#include <linux/completion.h>
+#include <linux/libata.h>
#include <linux/list.h>
#include <linux/kref.h>
#include <scsi/scsi.h>
/*
* Literals
*/
-#define IPR_DRIVER_VERSION "2.1.2"
-#define IPR_DRIVER_DATE "(February 8, 2006)"
+#define IPR_DRIVER_VERSION "2.2.0"
+#define IPR_DRIVER_DATE "(September 25, 2006)"
/*
* IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
* This can be adjusted at runtime through sysfs device attributes.
*/
#define IPR_MAX_CMD_PER_LUN 6
+#define IPR_MAX_CMD_PER_ATA_LUN 1
/*
* IPR_NUM_BASE_CMD_BLKS: This defines the maximum number of
#define IPR_IOA_BUS 0xff
#define IPR_IOA_TARGET 0xff
#define IPR_IOA_LUN 0xff
-#define IPR_MAX_NUM_BUSES 8
+#define IPR_MAX_NUM_BUSES 16
#define IPR_MAX_BUS_TO_SCAN IPR_MAX_NUM_BUSES
#define IPR_NUM_RESET_RELOAD_RETRIES 3
#define IPR_MAX_SCSI_RATE(width) ((320 * 10) / ((width) / 8))
#define IPR_IOA_RES_HANDLE 0xffffffff
+#define IPR_INVALID_RES_HANDLE 0
#define IPR_IOA_RES_ADDR 0x00ffffff
/*
#define IPR_LUN_RESET 0x40
#define IPR_TARGET_RESET 0x20
#define IPR_BUS_RESET 0x10
+#define IPR_ATA_PHY_RESET 0x80
#define IPR_ID_HOST_RR_Q 0xC4
#define IPR_QUERY_IOA_CONFIG 0xC5
#define IPR_CANCEL_ALL_REQUESTS 0xCE
}__attribute__ ((packed));
struct ipr_config_table_entry {
- u8 service_level;
+ u8 proto;
+#define IPR_PROTO_SATA 0x02
+#define IPR_PROTO_SATA_ATAPI 0x03
+#define IPR_PROTO_SAS_STP 0x06
+#define IPR_PROTO_SAS_STP_ATAPI 0x07
u8 array_id;
u8 flags;
#define IPR_IS_IOA_RESOURCE 0x80
#define IPR_SUBTYPE_AF_DASD 0
#define IPR_SUBTYPE_GENERIC_SCSI 1
#define IPR_SUBTYPE_VOLUME_SET 2
+#define IPR_SUBTYPE_GENERIC_ATA 4
#define IPR_QUEUEING_MODEL(res) ((((res)->cfgte.flags) & 0x70) >> 4)
#define IPR_QUEUE_FROZEN_MODEL 0
#define IPR_RQTYPE_SCSICDB 0x00
#define IPR_RQTYPE_IOACMD 0x01
#define IPR_RQTYPE_HCAM 0x02
+#define IPR_RQTYPE_ATA_PASSTHRU 0x04
u8 luntar_luntrn;
__be16 timeout;
}__attribute__ ((packed, aligned(4)));
+struct ipr_ioarcb_ata_regs {
+ u8 flags;
+#define IPR_ATA_FLAG_PACKET_CMD 0x80
+#define IPR_ATA_FLAG_XFER_TYPE_DMA 0x40
+#define IPR_ATA_FLAG_STATUS_ON_GOOD_COMPLETION 0x20
+ u8 reserved[3];
+
+ __be16 data;
+ u8 feature;
+ u8 nsect;
+ u8 lbal;
+ u8 lbam;
+ u8 lbah;
+ u8 device;
+ u8 command;
+ u8 reserved2[3];
+ u8 hob_feature;
+ u8 hob_nsect;
+ u8 hob_lbal;
+ u8 hob_lbam;
+ u8 hob_lbah;
+ u8 ctl;
+}__attribute__ ((packed, aligned(4)));
+
+struct ipr_ioarcb_add_data {
+ union {
+ struct ipr_ioarcb_ata_regs regs;
+ __be32 add_cmd_parms[10];
+ }u;
+}__attribute__ ((packed, aligned(4)));
+
/* IOA Request Control Block 128 bytes */
struct ipr_ioarcb {
__be32 ioarcb_host_pci_addr;
struct ipr_cmd_pkt cmd_pkt;
__be32 add_cmd_parms_len;
- __be32 add_cmd_parms[10];
+ struct ipr_ioarcb_add_data add_data;
}__attribute__((packed, aligned (4)));
struct ipr_ioadl_desc {
__be32 ioa_data[2];
}__attribute__((packed, aligned (4)));
+struct ipr_ioasa_gata {
+ u8 error;
+ u8 nsect; /* Interrupt reason */
+ u8 lbal;
+ u8 lbam;
+ u8 lbah;
+ u8 device;
+ u8 status;
+ u8 alt_status; /* ATA CTL */
+ u8 hob_nsect;
+ u8 hob_lbal;
+ u8 hob_lbam;
+ u8 hob_lbah;
+}__attribute__((packed, aligned (4)));
+
struct ipr_auto_sense {
__be16 auto_sense_len;
__be16 ioa_data_len;
__be32 ioasc_specific; /* status code specific field */
#define IPR_ADDITIONAL_STATUS_FMT 0x80000000
#define IPR_AUTOSENSE_VALID 0x40000000
+#define IPR_ATA_DEVICE_WAS_RESET 0x20000000
#define IPR_IOASC_SPECIFIC_MASK 0x00ffffff
#define IPR_FIELD_POINTER_VALID (0x80000000 >> 8)
#define IPR_FIELD_POINTER_MASK 0x0000ffff
struct ipr_ioasa_vset vset;
struct ipr_ioasa_af_dasd dasd;
struct ipr_ioasa_gpdd gpdd;
+ struct ipr_ioasa_gata gata;
} u;
struct ipr_auto_sense auto_sense;
u32 max_xfer_rate;
};
+struct ipr_sata_port {
+ struct ipr_ioa_cfg *ioa_cfg;
+ struct ata_port *ap;
+ struct ipr_resource_entry *res;
+ struct ipr_ioasa_gata ioasa;
+};
+
struct ipr_resource_entry {
struct ipr_config_table_entry cfgte;
u8 needs_sync_complete:1;
u8 resetting_device:1;
struct scsi_device *sdev;
+ struct ipr_sata_port *sata_port;
struct list_head queue;
};
u32 time;
u8 op_code;
+ u8 ata_op_code;
u8 type;
#define IPR_TRACE_START 0x00
#define IPR_TRACE_FINISH 0xff
- u16 cmd_index;
+ u8 cmd_index;
__be32 res_handle;
union {
struct ipr_cmnd *reset_cmd;
+ struct ata_host ata_host;
char ipr_cmd_label[8];
#define IPR_CMD_LABEL "ipr_cmnd"
struct ipr_cmnd *ipr_cmnd_list[IPR_NUM_CMD_BLKS];
struct ipr_ioadl_desc ioadl[IPR_NUM_IOADL_ENTRIES];
struct list_head queue;
struct scsi_cmnd *scsi_cmd;
+ struct ata_queued_cmd *qc;
struct completion completion;
struct timer_list timer;
void (*done) (struct ipr_cmnd *);
*/
#define ipr_err(...) printk(KERN_ERR IPR_NAME ": "__VA_ARGS__)
#define ipr_info(...) printk(KERN_INFO IPR_NAME ": "__VA_ARGS__)
-#define ipr_crit(...) printk(KERN_CRIT IPR_NAME ": "__VA_ARGS__)
-#define ipr_warn(...) printk(KERN_WARNING IPR_NAME": "__VA_ARGS__)
#define ipr_dbg(...) IPR_DBG_CMD(printk(KERN_INFO IPR_NAME ": "__VA_ARGS__))
-#define ipr_sdev_printk(level, sdev, fmt, args...) \
- sdev_printk(level, sdev, fmt, ## args)
-
-#define ipr_sdev_err(sdev, fmt, ...) \
- ipr_sdev_printk(KERN_ERR, sdev, fmt, ##__VA_ARGS__)
+#define ipr_ra_printk(level, ioa_cfg, ra, fmt, ...) \
+ printk(level IPR_NAME ": %d:%d:%d:%d: " fmt, (ioa_cfg)->host->host_no, \
+ (ra).bus, (ra).target, (ra).lun, ##__VA_ARGS__)
-#define ipr_sdev_info(sdev, fmt, ...) \
- ipr_sdev_printk(KERN_INFO, sdev, fmt, ##__VA_ARGS__)
-
-#define ipr_sdev_dbg(sdev, fmt, ...) \
- IPR_DBG_CMD(ipr_sdev_printk(KERN_INFO, sdev, fmt, ##__VA_ARGS__))
-
-#define ipr_res_printk(level, ioa_cfg, res, fmt, ...) \
- printk(level IPR_NAME ": %d:%d:%d:%d: " fmt, ioa_cfg->host->host_no, \
- res.bus, res.target, res.lun, ##__VA_ARGS__)
+#define ipr_ra_err(ioa_cfg, ra, fmt, ...) \
+ ipr_ra_printk(KERN_ERR, ioa_cfg, ra, fmt, ##__VA_ARGS__)
#define ipr_res_err(ioa_cfg, res, fmt, ...) \
- ipr_res_printk(KERN_ERR, ioa_cfg, res, fmt, ##__VA_ARGS__)
-#define ipr_res_dbg(ioa_cfg, res, fmt, ...) \
- IPR_DBG_CMD(ipr_res_printk(KERN_INFO, ioa_cfg, res, fmt, ##__VA_ARGS__))
+ ipr_ra_err(ioa_cfg, (res)->cfgte.res_addr, fmt, ##__VA_ARGS__)
#define ipr_phys_res_err(ioa_cfg, res, fmt, ...) \
{ \
return 0;
}
+/**
+ * ipr_is_scsi_disk - Determine if a resource is a SCSI disk
+ * @res: resource entry struct
+ *
+ * Return value:
+ * 1 if SCSI disk / 0 if not SCSI disk
+ **/
+static inline int ipr_is_scsi_disk(struct ipr_resource_entry *res)
+{
+ if (ipr_is_af_dasd_device(res) ||
+ (ipr_is_gscsi(res) && IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data)))
+ return 1;
+ else
+ return 0;
+}
+
+/**
+ * ipr_is_gata - Determine if a resource is a generic ATA resource
+ * @res: resource entry struct
+ *
+ * Return value:
+ * 1 if GATA / 0 if not GATA
+ **/
+static inline int ipr_is_gata(struct ipr_resource_entry *res)
+{
+ if (!ipr_is_ioa_resource(res) &&
+ IPR_RES_SUBTYPE(res) == IPR_SUBTYPE_GENERIC_ATA)
+ return 1;
+ else
+ return 0;
+}
+
/**
* ipr_is_naca_model - Determine if a resource is using NACA queueing model
* @res: resource entry struct