forked from luck/tmp_suning_uos_patched
[SCSI] 3ware 9000 add big endian support
The attached patch updates the 3ware 9000 driver: - Fix 9550SX pchip reset timeout. - Add big endian support. Signed-off-by: Adam Radford <linuxraid@amcc.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
parent
95e6a85677
commit
75913d9bb8
|
@ -2,8 +2,9 @@
|
||||||
3w-9xxx.c -- 3ware 9000 Storage Controller device driver for Linux.
|
3w-9xxx.c -- 3ware 9000 Storage Controller device driver for Linux.
|
||||||
|
|
||||||
Written By: Adam Radford <linuxraid@amcc.com>
|
Written By: Adam Radford <linuxraid@amcc.com>
|
||||||
|
Modifications By: Tom Couch <linuxraid@amcc.com>
|
||||||
|
|
||||||
Copyright (C) 2004-2005 Applied Micro Circuits Corporation.
|
Copyright (C) 2004-2006 Applied Micro Circuits Corporation.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -62,6 +63,8 @@
|
||||||
2.26.02.003 - Correctly handle single sgl's with use_sg=1.
|
2.26.02.003 - Correctly handle single sgl's with use_sg=1.
|
||||||
2.26.02.004 - Add support for 9550SX controllers.
|
2.26.02.004 - Add support for 9550SX controllers.
|
||||||
2.26.02.005 - Fix use_sg == 0 mapping on systems with 4GB or higher.
|
2.26.02.005 - Fix use_sg == 0 mapping on systems with 4GB or higher.
|
||||||
|
2.26.02.006 - Fix 9550SX pchip reset timeout.
|
||||||
|
Add big endian support.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
@ -85,7 +88,7 @@
|
||||||
#include "3w-9xxx.h"
|
#include "3w-9xxx.h"
|
||||||
|
|
||||||
/* Globals */
|
/* Globals */
|
||||||
#define TW_DRIVER_VERSION "2.26.02.005"
|
#define TW_DRIVER_VERSION "2.26.02.006"
|
||||||
static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
|
static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
|
||||||
static unsigned int twa_device_extension_count;
|
static unsigned int twa_device_extension_count;
|
||||||
static int twa_major = -1;
|
static int twa_major = -1;
|
||||||
|
@ -208,7 +211,7 @@ static int twa_aen_complete(TW_Device_Extension *tw_dev, int request_id)
|
||||||
|
|
||||||
header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id];
|
header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id];
|
||||||
tw_dev->posted_request_count--;
|
tw_dev->posted_request_count--;
|
||||||
aen = header->status_block.error;
|
aen = le16_to_cpu(header->status_block.error);
|
||||||
full_command_packet = tw_dev->command_packet_virt[request_id];
|
full_command_packet = tw_dev->command_packet_virt[request_id];
|
||||||
command_packet = &full_command_packet->command.oldcommand;
|
command_packet = &full_command_packet->command.oldcommand;
|
||||||
|
|
||||||
|
@ -305,7 +308,7 @@ static int twa_aen_drain_queue(TW_Device_Extension *tw_dev, int no_check_reset)
|
||||||
|
|
||||||
tw_dev->posted_request_count--;
|
tw_dev->posted_request_count--;
|
||||||
header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id];
|
header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id];
|
||||||
aen = header->status_block.error;
|
aen = le16_to_cpu(header->status_block.error);
|
||||||
queue = 0;
|
queue = 0;
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
|
@ -365,7 +368,7 @@ static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H
|
||||||
tw_dev->aen_clobber = 1;
|
tw_dev->aen_clobber = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
aen = header->status_block.error;
|
aen = le16_to_cpu(header->status_block.error);
|
||||||
memset(event, 0, sizeof(TW_Event));
|
memset(event, 0, sizeof(TW_Event));
|
||||||
|
|
||||||
event->severity = TW_SEV_OUT(header->status_block.severity__reserved);
|
event->severity = TW_SEV_OUT(header->status_block.severity__reserved);
|
||||||
|
@ -382,7 +385,7 @@ static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H
|
||||||
|
|
||||||
header->err_specific_desc[sizeof(header->err_specific_desc) - 1] = '\0';
|
header->err_specific_desc[sizeof(header->err_specific_desc) - 1] = '\0';
|
||||||
event->parameter_len = strlen(header->err_specific_desc);
|
event->parameter_len = strlen(header->err_specific_desc);
|
||||||
memcpy(event->parameter_data, header->err_specific_desc, event->parameter_len);
|
memcpy(event->parameter_data, header->err_specific_desc, event->parameter_len + (error_str[0] == '\0' ? 0 : (1 + strlen(error_str))));
|
||||||
if (event->severity != TW_AEN_SEVERITY_DEBUG)
|
if (event->severity != TW_AEN_SEVERITY_DEBUG)
|
||||||
printk(KERN_WARNING "3w-9xxx:%s AEN: %s (0x%02X:0x%04X): %s:%s.\n",
|
printk(KERN_WARNING "3w-9xxx:%s AEN: %s (0x%02X:0x%04X): %s:%s.\n",
|
||||||
host,
|
host,
|
||||||
|
@ -462,24 +465,24 @@ static void twa_aen_sync_time(TW_Device_Extension *tw_dev, int request_id)
|
||||||
command_packet = &full_command_packet->command.oldcommand;
|
command_packet = &full_command_packet->command.oldcommand;
|
||||||
command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_SET_PARAM);
|
command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_SET_PARAM);
|
||||||
command_packet->request_id = request_id;
|
command_packet->request_id = request_id;
|
||||||
command_packet->byte8_offset.param.sgl[0].address = tw_dev->generic_buffer_phys[request_id];
|
command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
|
||||||
command_packet->byte8_offset.param.sgl[0].length = TW_SECTOR_SIZE;
|
command_packet->byte8_offset.param.sgl[0].length = cpu_to_le32(TW_SECTOR_SIZE);
|
||||||
command_packet->size = TW_COMMAND_SIZE;
|
command_packet->size = TW_COMMAND_SIZE;
|
||||||
command_packet->byte6_offset.parameter_count = 1;
|
command_packet->byte6_offset.parameter_count = cpu_to_le16(1);
|
||||||
|
|
||||||
/* Setup the param */
|
/* Setup the param */
|
||||||
param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id];
|
param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id];
|
||||||
memset(param, 0, TW_SECTOR_SIZE);
|
memset(param, 0, TW_SECTOR_SIZE);
|
||||||
param->table_id = TW_TIMEKEEP_TABLE | 0x8000; /* Controller time keep table */
|
param->table_id = cpu_to_le16(TW_TIMEKEEP_TABLE | 0x8000); /* Controller time keep table */
|
||||||
param->parameter_id = 0x3; /* SchedulerTime */
|
param->parameter_id = cpu_to_le16(0x3); /* SchedulerTime */
|
||||||
param->parameter_size_bytes = 4;
|
param->parameter_size_bytes = cpu_to_le16(4);
|
||||||
|
|
||||||
/* Convert system time in UTC to local time seconds since last
|
/* Convert system time in UTC to local time seconds since last
|
||||||
Sunday 12:00AM */
|
Sunday 12:00AM */
|
||||||
do_gettimeofday(&utc);
|
do_gettimeofday(&utc);
|
||||||
local_time = (u32)(utc.tv_sec - (sys_tz.tz_minuteswest * 60));
|
local_time = (u32)(utc.tv_sec - (sys_tz.tz_minuteswest * 60));
|
||||||
schedulertime = local_time - (3 * 86400);
|
schedulertime = local_time - (3 * 86400);
|
||||||
schedulertime = schedulertime % 604800;
|
schedulertime = cpu_to_le32(schedulertime % 604800);
|
||||||
|
|
||||||
memcpy(param->data, &schedulertime, sizeof(u32));
|
memcpy(param->data, &schedulertime, sizeof(u32));
|
||||||
|
|
||||||
|
@ -931,26 +934,19 @@ static int twa_empty_response_queue(TW_Device_Extension *tw_dev)
|
||||||
/* This function will clear the pchip/response queue on 9550SX */
|
/* This function will clear the pchip/response queue on 9550SX */
|
||||||
static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev)
|
static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev)
|
||||||
{
|
{
|
||||||
u32 status_reg_value, response_que_value;
|
u32 response_que_value = 0;
|
||||||
int count = 0, retval = 1;
|
unsigned long before;
|
||||||
|
int retval = 1;
|
||||||
|
|
||||||
if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) {
|
if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) {
|
||||||
status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
|
before = jiffies;
|
||||||
|
while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != TW_9550SX_DRAIN_COMPLETED) {
|
||||||
while (((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) && (count < TW_MAX_RESPONSE_DRAIN)) {
|
|
||||||
response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev));
|
response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev));
|
||||||
if ((response_que_value & TW_9550SX_DRAIN_COMPLETED) == TW_9550SX_DRAIN_COMPLETED) {
|
if (time_after(jiffies, before + HZ * 30))
|
||||||
/* P-chip settle time */
|
|
||||||
msleep(500);
|
|
||||||
retval = 0;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
|
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
if (count == TW_MAX_RESPONSE_DRAIN)
|
/* P-chip settle time */
|
||||||
goto out;
|
msleep(500);
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
} else
|
} else
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
@ -972,7 +968,7 @@ static int twa_fill_sense(TW_Device_Extension *tw_dev, int request_id, int copy_
|
||||||
error_str = &(full_command_packet->header.err_specific_desc[strlen(full_command_packet->header.err_specific_desc) + 1]);
|
error_str = &(full_command_packet->header.err_specific_desc[strlen(full_command_packet->header.err_specific_desc) + 1]);
|
||||||
|
|
||||||
/* Don't print error for Logical unit not supported during rollcall */
|
/* Don't print error for Logical unit not supported during rollcall */
|
||||||
error = full_command_packet->header.status_block.error;
|
error = le16_to_cpu(full_command_packet->header.status_block.error);
|
||||||
if ((error != TW_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) && (error != TW_ERROR_UNIT_OFFLINE)) {
|
if ((error != TW_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) && (error != TW_ERROR_UNIT_OFFLINE)) {
|
||||||
if (print_host)
|
if (print_host)
|
||||||
printk(KERN_WARNING "3w-9xxx: scsi%d: ERROR: (0x%02X:0x%04X): %s:%s.\n",
|
printk(KERN_WARNING "3w-9xxx: scsi%d: ERROR: (0x%02X:0x%04X): %s:%s.\n",
|
||||||
|
@ -1047,18 +1043,18 @@ static void *twa_get_param(TW_Device_Extension *tw_dev, int request_id, int tabl
|
||||||
command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
|
command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
|
||||||
command_packet->size = TW_COMMAND_SIZE;
|
command_packet->size = TW_COMMAND_SIZE;
|
||||||
command_packet->request_id = request_id;
|
command_packet->request_id = request_id;
|
||||||
command_packet->byte6_offset.block_count = 1;
|
command_packet->byte6_offset.block_count = cpu_to_le16(1);
|
||||||
|
|
||||||
/* Now setup the param */
|
/* Now setup the param */
|
||||||
param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id];
|
param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id];
|
||||||
memset(param, 0, TW_SECTOR_SIZE);
|
memset(param, 0, TW_SECTOR_SIZE);
|
||||||
param->table_id = table_id | 0x8000;
|
param->table_id = cpu_to_le16(table_id | 0x8000);
|
||||||
param->parameter_id = parameter_id;
|
param->parameter_id = cpu_to_le16(parameter_id);
|
||||||
param->parameter_size_bytes = parameter_size_bytes;
|
param->parameter_size_bytes = cpu_to_le16(parameter_size_bytes);
|
||||||
param_value = tw_dev->generic_buffer_phys[request_id];
|
param_value = tw_dev->generic_buffer_phys[request_id];
|
||||||
|
|
||||||
command_packet->byte8_offset.param.sgl[0].address = param_value;
|
command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(param_value);
|
||||||
command_packet->byte8_offset.param.sgl[0].length = TW_SECTOR_SIZE;
|
command_packet->byte8_offset.param.sgl[0].length = cpu_to_le32(TW_SECTOR_SIZE);
|
||||||
|
|
||||||
/* Post the command packet to the board */
|
/* Post the command packet to the board */
|
||||||
twa_post_command_packet(tw_dev, request_id, 1);
|
twa_post_command_packet(tw_dev, request_id, 1);
|
||||||
|
@ -1107,18 +1103,20 @@ static int twa_initconnection(TW_Device_Extension *tw_dev, int message_credits,
|
||||||
tw_initconnect = (TW_Initconnect *)&full_command_packet->command.oldcommand;
|
tw_initconnect = (TW_Initconnect *)&full_command_packet->command.oldcommand;
|
||||||
tw_initconnect->opcode__reserved = TW_OPRES_IN(0, TW_OP_INIT_CONNECTION);
|
tw_initconnect->opcode__reserved = TW_OPRES_IN(0, TW_OP_INIT_CONNECTION);
|
||||||
tw_initconnect->request_id = request_id;
|
tw_initconnect->request_id = request_id;
|
||||||
tw_initconnect->message_credits = message_credits;
|
tw_initconnect->message_credits = cpu_to_le16(message_credits);
|
||||||
tw_initconnect->features = set_features;
|
tw_initconnect->features = set_features;
|
||||||
|
|
||||||
/* Turn on 64-bit sgl support if we need to */
|
/* Turn on 64-bit sgl support if we need to */
|
||||||
tw_initconnect->features |= sizeof(dma_addr_t) > 4 ? 1 : 0;
|
tw_initconnect->features |= sizeof(dma_addr_t) > 4 ? 1 : 0;
|
||||||
|
|
||||||
|
tw_initconnect->features = cpu_to_le32(tw_initconnect->features);
|
||||||
|
|
||||||
if (set_features & TW_EXTENDED_INIT_CONNECT) {
|
if (set_features & TW_EXTENDED_INIT_CONNECT) {
|
||||||
tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE_EXTENDED;
|
tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE_EXTENDED;
|
||||||
tw_initconnect->fw_srl = current_fw_srl;
|
tw_initconnect->fw_srl = cpu_to_le16(current_fw_srl);
|
||||||
tw_initconnect->fw_arch_id = current_fw_arch_id;
|
tw_initconnect->fw_arch_id = cpu_to_le16(current_fw_arch_id);
|
||||||
tw_initconnect->fw_branch = current_fw_branch;
|
tw_initconnect->fw_branch = cpu_to_le16(current_fw_branch);
|
||||||
tw_initconnect->fw_build = current_fw_build;
|
tw_initconnect->fw_build = cpu_to_le16(current_fw_build);
|
||||||
} else
|
} else
|
||||||
tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE;
|
tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE;
|
||||||
|
|
||||||
|
@ -1130,11 +1128,11 @@ static int twa_initconnection(TW_Device_Extension *tw_dev, int message_credits,
|
||||||
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x15, "No valid response during init connection");
|
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x15, "No valid response during init connection");
|
||||||
} else {
|
} else {
|
||||||
if (set_features & TW_EXTENDED_INIT_CONNECT) {
|
if (set_features & TW_EXTENDED_INIT_CONNECT) {
|
||||||
*fw_on_ctlr_srl = tw_initconnect->fw_srl;
|
*fw_on_ctlr_srl = le16_to_cpu(tw_initconnect->fw_srl);
|
||||||
*fw_on_ctlr_arch_id = tw_initconnect->fw_arch_id;
|
*fw_on_ctlr_arch_id = le16_to_cpu(tw_initconnect->fw_arch_id);
|
||||||
*fw_on_ctlr_branch = tw_initconnect->fw_branch;
|
*fw_on_ctlr_branch = le16_to_cpu(tw_initconnect->fw_branch);
|
||||||
*fw_on_ctlr_build = tw_initconnect->fw_build;
|
*fw_on_ctlr_build = le16_to_cpu(tw_initconnect->fw_build);
|
||||||
*init_connect_result = tw_initconnect->result;
|
*init_connect_result = le32_to_cpu(tw_initconnect->result);
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
}
|
}
|
||||||
|
@ -1358,10 +1356,10 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d
|
||||||
newcommand = &full_command_packet->command.newcommand;
|
newcommand = &full_command_packet->command.newcommand;
|
||||||
newcommand->request_id__lunl =
|
newcommand->request_id__lunl =
|
||||||
TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id);
|
TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id);
|
||||||
newcommand->sg_list[0].address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1;
|
newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1);
|
||||||
newcommand->sg_list[0].length = length;
|
newcommand->sg_list[0].length = cpu_to_le32(length);
|
||||||
newcommand->sgl_entries__lunh =
|
newcommand->sgl_entries__lunh =
|
||||||
TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), 1);
|
cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), 1));
|
||||||
} else {
|
} else {
|
||||||
oldcommand = &full_command_packet->command.oldcommand;
|
oldcommand = &full_command_packet->command.oldcommand;
|
||||||
oldcommand->request_id = request_id;
|
oldcommand->request_id = request_id;
|
||||||
|
@ -1369,8 +1367,8 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d
|
||||||
if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) {
|
if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) {
|
||||||
/* Load the sg list */
|
/* Load the sg list */
|
||||||
sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset));
|
sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset));
|
||||||
sgl->address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1;
|
sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1);
|
||||||
sgl->length = length;
|
sgl->length = cpu_to_le32(length);
|
||||||
|
|
||||||
if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4))
|
if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4))
|
||||||
oldcommand->size += 1;
|
oldcommand->size += 1;
|
||||||
|
@ -1828,10 +1826,10 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
|
||||||
if (srb) {
|
if (srb) {
|
||||||
command_packet->unit = srb->device->id;
|
command_packet->unit = srb->device->id;
|
||||||
command_packet->request_id__lunl =
|
command_packet->request_id__lunl =
|
||||||
TW_REQ_LUN_IN(srb->device->lun, request_id);
|
cpu_to_le16(TW_REQ_LUN_IN(srb->device->lun, request_id));
|
||||||
} else {
|
} else {
|
||||||
command_packet->request_id__lunl =
|
command_packet->request_id__lunl =
|
||||||
TW_REQ_LUN_IN(0, request_id);
|
cpu_to_le16(TW_REQ_LUN_IN(0, request_id));
|
||||||
command_packet->unit = 0;
|
command_packet->unit = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1841,8 +1839,8 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
|
||||||
/* Map sglist from scsi layer to cmd packet */
|
/* Map sglist from scsi layer to cmd packet */
|
||||||
if (tw_dev->srb[request_id]->use_sg == 0) {
|
if (tw_dev->srb[request_id]->use_sg == 0) {
|
||||||
if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) {
|
if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) {
|
||||||
command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id];
|
command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
|
||||||
command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH;
|
command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
|
||||||
if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)
|
if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)
|
||||||
memcpy(tw_dev->generic_buffer_virt[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen);
|
memcpy(tw_dev->generic_buffer_virt[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1850,12 +1848,12 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
|
||||||
if (buffaddr == 0)
|
if (buffaddr == 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
command_packet->sg_list[0].address = buffaddr;
|
command_packet->sg_list[0].address = TW_CPU_TO_SGL(buffaddr);
|
||||||
command_packet->sg_list[0].length = tw_dev->srb[request_id]->request_bufflen;
|
command_packet->sg_list[0].length = cpu_to_le32(tw_dev->srb[request_id]->request_bufflen);
|
||||||
}
|
}
|
||||||
command_packet->sgl_entries__lunh = TW_REQ_LUN_IN((srb->device->lun >> 4), 1);
|
command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), 1));
|
||||||
|
|
||||||
if (command_packet->sg_list[0].address & TW_ALIGNMENT_9000_SGL) {
|
if (command_packet->sg_list[0].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
|
||||||
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2d, "Found unaligned address during execute scsi");
|
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2d, "Found unaligned address during execute scsi");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1869,35 +1867,35 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
|
||||||
memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length);
|
memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length);
|
||||||
kunmap_atomic(buf - sg->offset, KM_IRQ0);
|
kunmap_atomic(buf - sg->offset, KM_IRQ0);
|
||||||
}
|
}
|
||||||
command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id];
|
command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
|
||||||
command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH;
|
command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
|
||||||
} else {
|
} else {
|
||||||
sg_count = twa_map_scsi_sg_data(tw_dev, request_id);
|
sg_count = twa_map_scsi_sg_data(tw_dev, request_id);
|
||||||
if (sg_count == 0)
|
if (sg_count == 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
for (i = 0; i < sg_count; i++) {
|
for (i = 0; i < sg_count; i++) {
|
||||||
command_packet->sg_list[i].address = sg_dma_address(&sglist[i]);
|
command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(&sglist[i]));
|
||||||
command_packet->sg_list[i].length = sg_dma_len(&sglist[i]);
|
command_packet->sg_list[i].length = cpu_to_le32(sg_dma_len(&sglist[i]));
|
||||||
if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) {
|
if (command_packet->sg_list[i].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
|
||||||
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi");
|
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
command_packet->sgl_entries__lunh = TW_REQ_LUN_IN((srb->device->lun >> 4), tw_dev->srb[request_id]->use_sg);
|
command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), tw_dev->srb[request_id]->use_sg));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Internal cdb post */
|
/* Internal cdb post */
|
||||||
for (i = 0; i < use_sg; i++) {
|
for (i = 0; i < use_sg; i++) {
|
||||||
command_packet->sg_list[i].address = sglistarg[i].address;
|
command_packet->sg_list[i].address = TW_CPU_TO_SGL(sglistarg[i].address);
|
||||||
command_packet->sg_list[i].length = sglistarg[i].length;
|
command_packet->sg_list[i].length = cpu_to_le32(sglistarg[i].length);
|
||||||
if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) {
|
if (command_packet->sg_list[i].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
|
||||||
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2f, "Found unaligned sgl address during internal post");
|
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2f, "Found unaligned sgl address during internal post");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
command_packet->sgl_entries__lunh = TW_REQ_LUN_IN(0, use_sg);
|
command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN(0, use_sg));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (srb) {
|
if (srb) {
|
||||||
|
@ -2115,8 +2113,8 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
|
||||||
TW_PARAM_FWVER, TW_PARAM_FWVER_LENGTH),
|
TW_PARAM_FWVER, TW_PARAM_FWVER_LENGTH),
|
||||||
(char *)twa_get_param(tw_dev, 1, TW_VERSION_TABLE,
|
(char *)twa_get_param(tw_dev, 1, TW_VERSION_TABLE,
|
||||||
TW_PARAM_BIOSVER, TW_PARAM_BIOSVER_LENGTH),
|
TW_PARAM_BIOSVER, TW_PARAM_BIOSVER_LENGTH),
|
||||||
*(int *)twa_get_param(tw_dev, 2, TW_INFORMATION_TABLE,
|
le32_to_cpu(*(int *)twa_get_param(tw_dev, 2, TW_INFORMATION_TABLE,
|
||||||
TW_PARAM_PORTCOUNT, TW_PARAM_PORTCOUNT_LENGTH));
|
TW_PARAM_PORTCOUNT, TW_PARAM_PORTCOUNT_LENGTH)));
|
||||||
|
|
||||||
/* Now setup the interrupt handler */
|
/* Now setup the interrupt handler */
|
||||||
retval = request_irq(pdev->irq, twa_interrupt, SA_SHIRQ, "3w-9xxx", tw_dev);
|
retval = request_irq(pdev->irq, twa_interrupt, SA_SHIRQ, "3w-9xxx", tw_dev);
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
3w-9xxx.h -- 3ware 9000 Storage Controller device driver for Linux.
|
3w-9xxx.h -- 3ware 9000 Storage Controller device driver for Linux.
|
||||||
|
|
||||||
Written By: Adam Radford <linuxraid@amcc.com>
|
Written By: Adam Radford <linuxraid@amcc.com>
|
||||||
|
Modifications By: Tom Couch <linuxraid@amcc.com>
|
||||||
|
|
||||||
Copyright (C) 2004-2005 Applied Micro Circuits Corporation.
|
Copyright (C) 2004-2006 Applied Micro Circuits Corporation.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -287,9 +288,6 @@ static twa_message_type twa_error_table[] = {
|
||||||
#define TW_STATUS_UNEXPECTED_BITS 0x00F00000
|
#define TW_STATUS_UNEXPECTED_BITS 0x00F00000
|
||||||
#define TW_STATUS_VALID_INTERRUPT 0x00DF0000
|
#define TW_STATUS_VALID_INTERRUPT 0x00DF0000
|
||||||
|
|
||||||
/* RESPONSE QUEUE BIT DEFINITIONS */
|
|
||||||
#define TW_RESPONSE_ID_MASK 0x00000FF0
|
|
||||||
|
|
||||||
/* PCI related defines */
|
/* PCI related defines */
|
||||||
#define TW_NUMDEVICES 1
|
#define TW_NUMDEVICES 1
|
||||||
#define TW_PCI_CLEAR_PARITY_ERRORS 0xc100
|
#define TW_PCI_CLEAR_PARITY_ERRORS 0xc100
|
||||||
|
@ -471,6 +469,7 @@ printk(KERN_WARNING "3w-9xxx: ERROR: (0x%02X:0x%04X): %s.\n",a,b,c); \
|
||||||
#define TW_APACHE_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 72 : 109)
|
#define TW_APACHE_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 72 : 109)
|
||||||
#define TW_ESCALADE_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 41 : 62)
|
#define TW_ESCALADE_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 41 : 62)
|
||||||
#define TW_PADDING_LENGTH (sizeof(dma_addr_t) > 4 ? 8 : 0)
|
#define TW_PADDING_LENGTH (sizeof(dma_addr_t) > 4 ? 8 : 0)
|
||||||
|
#define TW_CPU_TO_SGL(x) (sizeof(dma_addr_t) > 4 ? cpu_to_le64(x) : cpu_to_le32(x))
|
||||||
|
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
|
||||||
|
@ -614,13 +613,6 @@ typedef union TAG_TW_Response_Queue {
|
||||||
u32 value;
|
u32 value;
|
||||||
} TW_Response_Queue;
|
} TW_Response_Queue;
|
||||||
|
|
||||||
typedef struct TAG_TW_Info {
|
|
||||||
char *buffer;
|
|
||||||
int length;
|
|
||||||
int offset;
|
|
||||||
int position;
|
|
||||||
} TW_Info;
|
|
||||||
|
|
||||||
/* Compatibility information structure */
|
/* Compatibility information structure */
|
||||||
typedef struct TAG_TW_Compatibility_Info
|
typedef struct TAG_TW_Compatibility_Info
|
||||||
{
|
{
|
||||||
|
@ -636,6 +628,8 @@ typedef struct TAG_TW_Compatibility_Info
|
||||||
unsigned short driver_build_low;
|
unsigned short driver_build_low;
|
||||||
} TW_Compatibility_Info;
|
} TW_Compatibility_Info;
|
||||||
|
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
typedef struct TAG_TW_Device_Extension {
|
typedef struct TAG_TW_Device_Extension {
|
||||||
u32 __iomem *base_addr;
|
u32 __iomem *base_addr;
|
||||||
unsigned long *generic_buffer_virt[TW_Q_LENGTH];
|
unsigned long *generic_buffer_virt[TW_Q_LENGTH];
|
||||||
|
@ -679,7 +673,5 @@ typedef struct TAG_TW_Device_Extension {
|
||||||
unsigned short working_build;
|
unsigned short working_build;
|
||||||
} TW_Device_Extension;
|
} TW_Device_Extension;
|
||||||
|
|
||||||
#pragma pack()
|
|
||||||
|
|
||||||
#endif /* _3W_9XXX_H */
|
#endif /* _3W_9XXX_H */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user