Changes corresponding to the 9.1.5.2 release of twa on the 3ware website.

The main changes are:
1. Use of multiple bus dma tags.
2. Timing of CAM requests by the driver.
3, Firmware interface change relating to retrieving AEN's.
4. Removal of twa_intrhook.
5. Bundling of latest firmware with BBU capability.

Reviewed by:re
Approved by:re
This commit is contained in:
Vinod Kashyap 2005-01-05 19:04:28 +00:00
parent 4c985f4a06
commit 5552eed8e5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=139723
8 changed files with 25947 additions and 23284 deletions

View file

@ -73,7 +73,8 @@ static void twa_command_intr(struct twa_softc *sc);
static int twa_fetch_aen(struct twa_softc *sc);
static void twa_aen_callback(struct twa_request *tr);
static void twa_enqueue_aen(struct twa_softc *sc, struct twa_command_header *cmd_hdr);
static unsigned short twa_enqueue_aen(struct twa_softc *sc,
struct twa_command_header *cmd_hdr);
static int twa_drain_aen_queue(struct twa_softc *sc);
static int twa_find_aen(struct twa_softc *sc, u_int16_t aen_code);
@ -125,10 +126,7 @@ twa_setup(struct twa_softc *sc)
for (i = 0; i < TWA_Q_LENGTH; i++)
sc->twa_aen_queue[i] = &(aen_queue[i]);
/*
* Disable interrupts from the card.
* Interrupts will be enabled back in twa_intrhook.
*/
/* Disable interrupts. */
twa_disable_interrupts(sc);
/* Initialize the controller. */
@ -157,10 +155,12 @@ static int
twa_flash_firmware(struct twa_softc *sc)
{
struct twa_request *tr;
struct twa_command_header *cmd_hdr;
struct twa_command_download_firmware *cmd;
u_int32_t fw_img_chunk_size;
u_int32_t this_chunk_size = 0;
u_int32_t remaining_img_size = 0;
u_int8_t *error_str;
int error;
int i;
@ -178,13 +178,14 @@ twa_flash_firmware(struct twa_softc *sc)
goto out;
}
remaining_img_size = twa_fw_img_size;
cmd_hdr = &(tr->tr_command->cmd_hdr);
cmd = &(tr->tr_command->command.cmd_pkt_7k.download_fw);
for (i = 0; i < NUM_FW_IMAGE_CHUNKS; i++) {
/* Build a cmd pkt for downloading firmware. */
bzero(tr->tr_command, sizeof(struct twa_command_packet));
tr->tr_command->cmd_hdr.header_desc.size_header = 128;
cmd_hdr->header_desc.size_header = 128;
cmd->opcode = TWA_OP_DOWNLOAD_FIRMWARE;
cmd->sgl_offset = 2;/* offset in dwords, to the beginning of sg list */
@ -221,13 +222,18 @@ twa_flash_firmware(struct twa_softc *sc)
}
error = cmd->status;
if (i != (NUM_FW_IMAGE_CHUNKS - 1)) {
if ((error = tr->tr_command->cmd_hdr.status_block.error) != TWA_ERROR_MORE_DATA) {
if ((error = cmd_hdr->status_block.error) != TWA_ERROR_MORE_DATA) {
error_str =
&(cmd_hdr->err_desc[strlen(cmd_hdr->err_desc) + 1]);
if (error_str[0] == '\0')
error_str = twa_find_msg_string(twa_error_table, error);
twa_printf(sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
cmd->opcode,
TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
error,
twa_find_msg_string(twa_error_table, error),
tr->tr_command->cmd_hdr.err_specific_desc);
error_str,
cmd_hdr->err_desc);
twa_printf(sc, "Firmware flash request failed. Intermediate error = 0x%x, i = %x\n",
cmd->status, i);
/* Hard reset the controller, so that it doesn't wait for the remaining chunks. */
@ -236,13 +242,18 @@ twa_flash_firmware(struct twa_softc *sc)
}
} else /* last chunk */
if (error) {
error_str =
&(cmd_hdr->err_desc[strlen(cmd_hdr->err_desc) + 1]);
if (error_str[0] == '\0')
error_str = twa_find_msg_string(twa_error_table,
cmd_hdr->status_block.error);
twa_printf(sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
cmd->opcode,
TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
tr->tr_command->cmd_hdr.status_block.error,
twa_find_msg_string(twa_error_table,
tr->tr_command->cmd_hdr.status_block.error),
tr->tr_command->cmd_hdr.err_specific_desc);
cmd_hdr->status_block.error,
error_str,
cmd_hdr->err_desc);
twa_printf(sc, "Firmware flash request failed. error = 0x%x\n", error);
/* Hard reset the controller, so that it doesn't wait for more chunks. */
twa_hard_reset(sc);
@ -271,6 +282,7 @@ static int
twa_hard_reset(struct twa_softc *sc)
{
struct twa_request *tr;
struct twa_command_header *cmd_hdr;
struct twa_command_reset_firmware *cmd;
int error;
@ -278,7 +290,8 @@ twa_hard_reset(struct twa_softc *sc)
return(EIO);
tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_INTERNAL;
/* Build a cmd pkt for sending down the hard reset command. */
tr->tr_command->cmd_hdr.header_desc.size_header = 128;
cmd_hdr = &(tr->tr_command->cmd_hdr);
cmd_hdr->header_desc.size_header = 128;
cmd = &(tr->tr_command->command.cmd_pkt_7k.reset_fw);
cmd->opcode = TWA_OP_RESET_FIRMWARE;
@ -301,13 +314,19 @@ twa_hard_reset(struct twa_softc *sc)
goto out;
}
if ((error = cmd->status)) {
u_int8_t *error_str =
&(cmd_hdr->err_desc[strlen(cmd_hdr->err_desc) + 1]);
if (error_str[0] == '\0')
error_str = twa_find_msg_string(twa_error_table,
cmd_hdr->status_block.error);
twa_printf(sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
cmd->opcode,
TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
tr->tr_command->cmd_hdr.status_block.error,
twa_find_msg_string(twa_error_table,
tr->tr_command->cmd_hdr.status_block.error),
tr->tr_command->cmd_hdr.err_specific_desc);
cmd_hdr->status_block.error,
error_str,
cmd_hdr->err_desc);
twa_printf(sc, "Hard reset request failed. error = 0x%x\n", error);
}
@ -472,6 +491,7 @@ twa_init_ctlr(struct twa_softc *sc)
/* Set controller state to initialized. */
sc->twa_state &= ~TWA_STATE_SHUTDOWN;
twa_enable_interrupts(sc);
twa_dbg_dprint_exit(3, sc);
return(0);
}
@ -516,7 +536,9 @@ void
twa_interrupt(struct twa_softc *sc)
{
u_int32_t status_reg;
int s;
s = splcam();
twa_dbg_dprint_enter(5, sc);
/* Collect current interrupt status. */
@ -533,6 +555,7 @@ twa_interrupt(struct twa_softc *sc)
twa_command_intr(sc);
if (status_reg & TWA_STATUS_RESPONSE_INTERRUPT)
twa_done(sc);
splx(s);
}
@ -928,10 +951,11 @@ static void *
twa_get_param(struct twa_softc *sc, int table_id, int param_id,
size_t param_size, void (* callback)(struct twa_request *tr))
{
struct twa_request *tr;
union twa_command_7k *cmd;
struct twa_param_9k *param = NULL;
int error = ENOMEM;
struct twa_request *tr;
struct twa_command_header *cmd_hdr;
union twa_command_7k *cmd;
struct twa_param_9k *param = NULL;
int error = ENOMEM;
twa_dbg_dprint_enter(4, sc);
@ -950,10 +974,10 @@ twa_get_param(struct twa_softc *sc, int table_id, int param_id,
tr->tr_flags = TWA_CMD_DATA_IN | TWA_CMD_DATA_OUT;
/* Build the cmd pkt. */
cmd = &(tr->tr_command->command.cmd_pkt_7k);
tr->tr_command->cmd_hdr.header_desc.size_header = 128;
cmd_hdr = &(tr->tr_command->cmd_hdr);
cmd_hdr->header_desc.size_header = 128;
cmd = &(tr->tr_command->command.cmd_pkt_7k);
cmd->param.opcode = TWA_OP_GET_PARAM;
cmd->param.sgl_offset = 2;
cmd->param.size = 2;
@ -975,13 +999,19 @@ twa_get_param(struct twa_softc *sc, int table_id, int param_id,
if (error)
goto out;
if ((error = cmd->param.status)) {
u_int8_t *error_str =
&(cmd_hdr->err_desc[strlen(cmd_hdr->err_desc) + 1]);
if (error_str[0] == '\0')
error_str = twa_find_msg_string(twa_error_table,
cmd_hdr->status_block.error);
twa_printf(sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
cmd->param.opcode,
TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
tr->tr_command->cmd_hdr.status_block.error,
twa_find_msg_string(twa_error_table,
tr->tr_command->cmd_hdr.status_block.error),
tr->tr_command->cmd_hdr.err_specific_desc);
cmd_hdr->status_block.error,
error_str,
cmd_hdr->err_desc);
goto out; /* twa_drain_complete_queue will have done the unmapping */
}
twa_release_request(tr);
@ -1026,10 +1056,11 @@ twa_set_param(struct twa_softc *sc, int table_id,
int param_id, int param_size, void *data,
void (* callback)(struct twa_request *tr))
{
struct twa_request *tr;
union twa_command_7k *cmd;
struct twa_param_9k *param = NULL;
int error = ENOMEM;
struct twa_request *tr;
struct twa_command_header *cmd_hdr;
union twa_command_7k *cmd;
struct twa_param_9k *param = NULL;
int error = ENOMEM;
twa_dbg_dprint_enter(4, sc);
@ -1048,10 +1079,10 @@ twa_set_param(struct twa_softc *sc, int table_id,
tr->tr_flags = TWA_CMD_DATA_IN | TWA_CMD_DATA_OUT;
/* Build the cmd pkt. */
cmd_hdr = &(tr->tr_command->cmd_hdr);
cmd_hdr->header_desc.size_header = 128;
cmd = &(tr->tr_command->command.cmd_pkt_7k);
tr->tr_command->cmd_hdr.header_desc.size_header = 128;
cmd->param.opcode = TWA_OP_SET_PARAM;
cmd->param.sgl_offset = 2;
cmd->param.size = 2;
@ -1074,13 +1105,18 @@ twa_set_param(struct twa_softc *sc, int table_id,
if (error)
goto out;
if ((error = cmd->param.status)) {
u_int8_t *error_str =
&(cmd_hdr->err_desc[strlen(cmd_hdr->err_desc) + 1]);
if (error_str[0] == '\0')
error_str = twa_find_msg_string(twa_error_table,
cmd_hdr->status_block.error);
twa_printf(sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
cmd->param.opcode,
TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
tr->tr_command->cmd_hdr.status_block.error,
twa_find_msg_string(twa_error_table,
tr->tr_command->cmd_hdr.status_block.error),
tr->tr_command->cmd_hdr.err_specific_desc);
cmd_hdr->status_block.error,
error_str,
cmd_hdr->err_desc);
goto out; /* twa_drain_complete_queue will have done the unmapping */
}
free(param, M_DEVBUF);
@ -1148,6 +1184,7 @@ twa_init_connection(struct twa_softc *sc, u_int16_t message_credits,
u_int16_t *fw_on_ctlr_build, u_int32_t *init_connect_result)
{
struct twa_request *tr;
struct twa_command_header *cmd_hdr;
struct twa_command_init_connect *init_connect;
int error = 1;
@ -1158,10 +1195,10 @@ twa_init_connection(struct twa_softc *sc, u_int16_t message_credits,
goto out;
tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_INTERNAL;
/* Build the cmd pkt. */
cmd_hdr = &(tr->tr_command->cmd_hdr);
cmd_hdr->header_desc.size_header = 128;
init_connect = &(tr->tr_command->command.cmd_pkt_7k.init_connect);
tr->tr_command->cmd_hdr.header_desc.size_header = 128;
init_connect->opcode = TWA_OP_INIT_CONNECTION;
init_connect->request_id = tr->tr_request_id;
init_connect->message_credits = message_credits;
@ -1185,13 +1222,18 @@ twa_init_connection(struct twa_softc *sc, u_int16_t message_credits,
if (error)
goto out;
if ((error = init_connect->status)) {
u_int8_t *error_str =
&(cmd_hdr->err_desc[strlen(cmd_hdr->err_desc) + 1]);
if (error_str[0] == '\0')
error_str = twa_find_msg_string(twa_error_table,
cmd_hdr->status_block.error);
twa_printf(sc, "cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
init_connect->opcode,
TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
tr->tr_command->cmd_hdr.status_block.error,
twa_find_msg_string(twa_error_table,
tr->tr_command->cmd_hdr.status_block.error),
tr->tr_command->cmd_hdr.err_specific_desc);
cmd_hdr->status_block.error,
error_str,
cmd_hdr->err_desc);
goto out; /* twa_drain_complete_queue will have done the unmapping */
}
if (set_features & TWA_EXTENDED_INIT_CONNECT) {
@ -1228,6 +1270,7 @@ static int
twa_wait_request(struct twa_request *tr, u_int32_t timeout)
{
time_t end_time;
int s;
int error;
twa_dbg_dprint_enter(4, tr->tr_sc);
@ -1240,14 +1283,18 @@ twa_wait_request(struct twa_request *tr, u_int32_t timeout)
return(error);
}
s = splcam();
end_time = time_second + timeout;
while (tr->tr_status != TWA_CMD_COMPLETE) {
if ((error = tr->tr_error))
return(error);
goto err;
if ((error = tsleep(tr, PRIBIO, "twawait", timeout * hz)) == 0) {
if ((error = tr->tr_error)) /* possible reset */
goto err;
error = (tr->tr_status != TWA_CMD_COMPLETE);
break;
}
tr->tr_flags &= ~TWA_CMD_SLEEP_ON_REQUEST;
if (error == EWOULDBLOCK) {
/* Time out! */
twa_printf(tr->tr_sc, "%s: Request %p timed out.\n",
@ -1267,10 +1314,11 @@ twa_wait_request(struct twa_request *tr, u_int32_t timeout)
/* Request was never submitted. Clean up. */
twa_remove_pending(tr);
twa_unmap_request(tr);
if (tr->tr_data)
free(tr->tr_data, M_DEVBUF);
twa_release_request(tr);
}
if (tr->tr_data)
free(tr->tr_data, M_DEVBUF);
twa_release_request(tr);
splx(s);
return(ETIMEDOUT);
}
/*
@ -1280,6 +1328,9 @@ twa_wait_request(struct twa_request *tr, u_int32_t timeout)
timeout = (end_time - time_second);
}
twa_unmap_request(tr);
err:
splx(s);
return(error);
}
@ -1396,6 +1447,14 @@ twa_reset(struct twa_softc *sc)
twa_disable_interrupts(sc);
s = splcam();
/*
* Complete all requests in the complete queue; error back all requests
* in the busy queue. Any internal requests will be simply freed.
* Re-submit any requests in the pending queue.
*/
twa_drain_complete_queue(sc);
twa_drain_busy_queue(sc);
/* Soft reset the controller. */
if ((error = twa_soft_reset(sc))) {
twa_printf (sc, "Controller reset failed.\n");
@ -1412,14 +1471,6 @@ twa_reset(struct twa_softc *sc)
twa_printf(sc, "Controller reset done!\n");
/*
* Complete all requests in the complete queue; error back all requests
* in the busy queue. Any internal requests will be simply freed.
* Re-submit any requests in the pending queue.
*/
twa_drain_complete_queue(sc);
twa_drain_busy_queue(sc);
out:
splx(s);
/*
@ -1568,13 +1619,13 @@ twa_start(struct twa_request *tr)
}
error = EBUSY;
} else {
/* Cmd queue is not full. Post the command. */
TWA_WRITE_COMMAND_QUEUE(sc,
tr->tr_cmd_phys + sizeof(struct twa_command_header));
/* Mark the request as currently being processed. */
tr->tr_status = TWA_CMD_BUSY;
/* Move the request into the busy queue. */
twa_enqueue_busy(tr);
/* Cmd queue is not full. Post the command. */
TWA_WRITE_COMMAND_QUEUE(sc,
tr->tr_cmd_phys + sizeof(struct twa_command_header));
}
out:
@ -1662,9 +1713,9 @@ twa_drain_pending_queue(struct twa_softc *sc)
} else {
twa_printf(sc, "%s: twa_start returned 0x%x\n",
__func__, error);
tr->tr_error = error;
if (tr->tr_flags & TWA_CMD_SLEEP_ON_REQUEST)
wakeup_one(tr);/* let the caller know it failed */
tr->tr_error = error;
error = 0;
}
}
@ -1735,7 +1786,7 @@ twa_wait_status(struct twa_softc *sc, u_int32_t status, u_int32_t timeout)
status_reg = TWA_READ_STATUS_REGISTER(sc);
if ((status_reg & status) == status)/* got the required bit(s)? */
return(0);
DELAY(100000);
DELAY(1000);
} while (time_second <= end_time);
return(1);
@ -1808,9 +1859,9 @@ twa_attention_intr(struct twa_softc *sc)
twa_dbg_dprint_enter(6, sc);
TWA_WRITE_CONTROL_REGISTER(sc, TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT);
if ((error = twa_fetch_aen(sc)))
twa_printf(sc, "Fetch AEN failed. error = 0x%x\n", error);
TWA_WRITE_CONTROL_REGISTER(sc, TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT);
}
@ -1830,10 +1881,13 @@ twa_command_intr(struct twa_softc *sc)
{
twa_dbg_dprint_enter(6, sc);
/* Start any requests that might be in the pending queue. */
if (! twa_drain_pending_queue(sc))
TWA_WRITE_CONTROL_REGISTER(sc,
TWA_CONTROL_MASK_COMMAND_INTERRUPT);
TWA_WRITE_CONTROL_REGISTER(sc, TWA_CONTROL_MASK_COMMAND_INTERRUPT);
/*
* Start any requests that might be in the pending queue.
* If all requests could not be started because of a queue_full
* condition, twa_start will have unmasked the command interrupt.
*/
twa_drain_pending_queue(sc);
}
@ -1881,8 +1935,11 @@ static void
twa_aen_callback(struct twa_request *tr)
{
struct twa_softc *sc = tr->tr_sc;
struct twa_command_header *cmd_hdr = (struct twa_command_header *)(tr->tr_data);
struct twa_command_header *cmd_hdr;
struct twa_command_9k *cmd = &(tr->tr_command->command.cmd_pkt_9k);
u_int8_t *error_str;
int fetch_more_aens = 0;
int error;
int i;
twa_dbg_dprint_enter(4, sc);
@ -1891,19 +1948,28 @@ twa_aen_callback(struct twa_request *tr)
cmd->request_id,
cmd->status);
if (tr->tr_error)
goto out;
if (! cmd->status) {
cmd_hdr = (struct twa_command_header *)(tr->tr_data);
if ((tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_9K) &&
(cmd->cdb[0] == 0x3 /* REQUEST_SENSE */))
twa_enqueue_aen(sc, cmd_hdr);
if (twa_enqueue_aen(sc, cmd_hdr) != TWA_AEN_QUEUE_EMPTY)
fetch_more_aens = 1;
} else {
cmd_hdr->err_specific_desc[sizeof(cmd_hdr->err_specific_desc) - 1] = '\0';
cmd_hdr = &(tr->tr_command->cmd_hdr);
error_str = &(cmd_hdr->err_desc[strlen(cmd_hdr->err_desc) + 1]);
if (error_str[0] == '\0')
error_str = twa_find_msg_string(twa_error_table,
cmd_hdr->status_block.error);
twa_printf(sc, "%s: cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
__func__, cmd->command.opcode,
TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
cmd_hdr->status_block.error,
twa_find_msg_string(twa_error_table,
cmd_hdr->status_block.error),
cmd_hdr->err_specific_desc);
error_str,
cmd_hdr->err_desc);
twa_dbg_print(2, "sense info: ");
for (i = 0; i < 18; i++)
twa_dbg_print(2, "%x\t", tr->tr_command->cmd_hdr.sense_data[i]);
@ -1912,9 +1978,14 @@ twa_aen_callback(struct twa_request *tr)
twa_dbg_print(7, "%x\t", ((int8_t *)(tr->tr_data))[i]);
}
out:
if (tr->tr_data)
free(tr->tr_data, M_DEVBUF);
twa_release_request(tr);
if (fetch_more_aens)
if ((error = twa_fetch_aen(sc)))
twa_printf(sc, "%s: Fetch AEN failed. error = 0x%x\n",
__func__, error);
}
@ -1964,10 +2035,8 @@ twa_drain_aen_queue(struct twa_softc *sc)
break;
cmd_hdr = (struct twa_command_header *)(tr->tr_data);
if ((cmd_hdr->status_block.error) /* aen_code */
== TWA_AEN_QUEUE_EMPTY)
if (twa_enqueue_aen(sc, cmd_hdr) == TWA_AEN_QUEUE_EMPTY)
break;
twa_enqueue_aen(sc, cmd_hdr);
free(tr->tr_data, M_DEVBUF);
twa_release_request(tr);
@ -1991,15 +2060,16 @@ twa_drain_aen_queue(struct twa_softc *sc)
* cmd_hdr -- ptr to hdr of fw cmd pkt, from where the AEN
* details can be retrieved.
* Output: None
* Return value: None
* Return value: AEN code
*/
static void
static unsigned short
twa_enqueue_aen(struct twa_softc *sc, struct twa_command_header *cmd_hdr)
{
struct twa_event_packet *event;
unsigned short aen_code;
unsigned long local_time;
unsigned long sync_time;
u_int8_t *aen_str;
int s;
twa_dbg_dprint_enter(4, sc);
@ -2035,12 +2105,18 @@ twa_enqueue_aen(struct twa_softc *sc, struct twa_command_header *cmd_hdr)
event->aen_code = aen_code;
event->retrieved = TWA_AEN_NOT_RETRIEVED;
event->sequence_id = ++(sc->twa_current_sequence_id);
cmd_hdr->err_specific_desc[sizeof(cmd_hdr->err_specific_desc) - 1] = '\0';
event->parameter_len = strlen(cmd_hdr->err_specific_desc);
bcopy(cmd_hdr->err_specific_desc, event->parameter_data,
aen_str = &(cmd_hdr->err_desc[strlen(cmd_hdr->err_desc) + 1]);
if (aen_str[0] == '\0')
aen_str = twa_find_msg_string(twa_aen_table, aen_code);
event->parameter_len = strlen(cmd_hdr->err_desc) +
strlen(aen_str) + 2;
bcopy(cmd_hdr->err_desc, event->parameter_data,
event->parameter_len);
twa_dbg_dprint(4, sc, "event = %x %x %x %x %x %x %x\n %s",
twa_dbg_dprint(4, sc, "event = %x %x %x %x %x %x %x\n %s %s",
event->sequence_id,
event->time_stamp_sec,
event->aen_code,
@ -2048,17 +2124,19 @@ twa_enqueue_aen(struct twa_softc *sc, struct twa_command_header *cmd_hdr)
event->retrieved,
event->repeat_count,
event->parameter_len,
&(event->parameter_data[strlen(cmd_hdr->err_desc) + 1]),
event->parameter_data);
twa_dbg_dprint(4, sc, "cmd_hdr = %x %lx %x %x %x %x %zx\n %s",
twa_dbg_dprint(4, sc, "cmd_hdr = %x %lx %x %x %x %x %zx\n %s %s",
sc->twa_current_sequence_id,
local_time,
cmd_hdr->status_block.error,
cmd_hdr->status_block.substatus_block.severity,
TWA_AEN_NOT_RETRIEVED,
0,
strlen(cmd_hdr->err_specific_desc),
cmd_hdr->err_specific_desc);
strlen(cmd_hdr->err_desc),
&(cmd_hdr->err_desc[strlen(cmd_hdr->err_desc) + 1]),
cmd_hdr->err_desc);
/* Print the event. */
if (event->severity < TWA_AEN_SEVERITY_DEBUG)
@ -2066,7 +2144,7 @@ twa_enqueue_aen(struct twa_softc *sc, struct twa_command_header *cmd_hdr)
twa_aen_severity_table[event->severity],
TWA_MESSAGE_SOURCE_CONTROLLER_EVENT,
aen_code,
twa_find_msg_string(twa_aen_table, aen_code),
aen_str,
event->parameter_data);
if ((sc->twa_aen_head + 1) == TWA_Q_LENGTH)
@ -2075,6 +2153,7 @@ twa_enqueue_aen(struct twa_softc *sc, struct twa_command_header *cmd_hdr)
break;
} /* switch */
splx(s);
return(aen_code);
}

View file

@ -35,11 +35,7 @@
*/
/*
* The scheme for the driver version is:
* <major change>.<external release>.<3ware internal release>.<development release>
*/
#define TWA_DRIVER_VERSION_STRING "2.50.00.000"
#define TWA_DRIVER_VERSION_STRING "2.50.02.011"
#define TWA_CDEV_MAJOR MAJOR_AUTO
@ -68,7 +64,9 @@
#define TWA_CMD_DATA_OUT (1<<1) /* write request */
#define TWA_CMD_DATA_COPY_NEEDED (1<<2) /* data in ccb is misaligned, have to copy to/from private buffer */
#define TWA_CMD_SLEEP_ON_REQUEST (1<<3) /* owner is sleeping on this command */
#define TWA_CMD_IN_PROGRESS (1<<4) /* bus_dmamap_load returned EINPROGRESS */
#define TWA_CMD_MAPPED (1<<4) /* request has been mapped */
#define TWA_CMD_IN_PROGRESS (1<<5) /* bus_dmamap_load returned EINPROGRESS */
#define TWA_CMD_TIMER_SET (1<<6) /* request is being timed */
/* Possible values of tr->tr_cmd_pkt_type. */
#define TWA_CMD_PKT_TYPE_7K (1<<0)
@ -114,10 +112,10 @@ struct twa_request {
u_int32_t tr_request_id; /* request id for tracking with firmware */
void *tr_data; /* ptr to data being passed to firmware */
size_t tr_length; /* length of buffer being passed to firmware */
u_int32_t tr_length; /* length of buffer being passed to firmware */
void *tr_real_data; /* ptr to, and length of data passed */
size_t tr_real_length; /* to us from above, in case a buffer copy
u_int32_t tr_real_length; /* to us from above, in case a buffer copy
was done due to non-compliance to
alignment requirements */
@ -131,7 +129,7 @@ struct twa_request {
void *tr_private; /* request specific data to use during callback */
void (*tr_callback)(struct twa_request *tr);/* callback handler */
bus_addr_t tr_cmd_phys; /* physical address of command in controller space */
bus_dmamap_t tr_dma_map; /* DMA map for data */
bus_dmamap_t tr_buf_map; /* DMA map for data */
} __attribute__ ((packed));
@ -174,11 +172,13 @@ struct twa_softc {
between ioctl calls */
device_t twa_bus_dev; /* bus device */
struct cdev *twa_ctrl_dev; /* control device */
struct cdev *twa_ctrl_dev; /* control device */
struct resource *twa_io_res; /* register interface window */
bus_space_handle_t twa_bus_handle; /* bus space handle */
bus_space_tag_t twa_bus_tag; /* bus space tag */
bus_dma_tag_t twa_dma_tag; /* data buffer DMA tag */
bus_dma_tag_t twa_parent_tag; /* parent DMA tag */
bus_dma_tag_t twa_cmd_tag; /* cmd DMA tag */
bus_dma_tag_t twa_buf_tag; /* data buffer DMA tag */
bus_dmamap_t twa_cmd_map; /* DMA map for the array of cmd pkts */
bus_addr_t twa_cmd_pkt_phys;/* phys addr of first of array of cmd pkts */
struct resource *twa_irq_res; /* interrupt resource*/

View file

@ -50,6 +50,7 @@ static int twa_execute_scsi(struct twa_request *tr, union ccb *ccb);
static void twa_action(struct cam_sim *sim, union ccb *ccb);
static void twa_poll(struct cam_sim *sim);
static void twa_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg);
static void twa_timeout(void *arg);
static void twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
@ -304,6 +305,9 @@ twa_execute_scsi(struct twa_request *tr, union ccb *ccb)
}
tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_9K;
twa_set_timer(tr);
/* twa_setup_data_dmamap will fill in the SGL, and submit the I/O. */
error = twa_map_request(tr);
return(error);
@ -405,9 +409,9 @@ twa_action(struct cam_sim *sim, union ccb *ccb)
twa_dbg_dprint(3, sc, "XPT_PATH_INQ request");
path_inq->version_num = 1;
path_inq->hba_inquiry = 0;
path_inq->hba_inquiry = PI_WIDE_16;
path_inq->target_sprt = 0;
path_inq->hba_misc = 0;
path_inq->hba_misc |= PIM_NOBUSRESET;
path_inq->hba_eng_cnt = 0;
path_inq->max_target = TWA_MAX_UNITS;
path_inq->max_lun = 0;
@ -482,6 +486,28 @@ twa_async(void *callback_arg, u_int32_t code,
/*
* Function name: twa_timeout
* Description: Driver entry point for being alerted on a request
* timing out.
*
* Input: arg -- ptr to timed out request
* Output: None
* Return value: None
*/
static void
twa_timeout(void *arg)
{
struct twa_request *tr = (struct twa_request *)arg;
struct twa_softc *sc = (struct twa_softc *)(tr->tr_sc);
twa_printf(sc, "Request timed out! tr = %p\n", tr);
twa_reset(sc);
}
/*
* Function name: twa_request_bus_scan
* Description: Requests CAM for a scan of the bus.
@ -555,6 +581,8 @@ twa_scsi_complete(struct twa_request *tr)
u_int16_t error;
u_int8_t *cdb;
twa_unset_timer(tr);
if (tr->tr_error) {
if (tr->tr_error == EBUSY)
ccb->ccb_h.status |= CAM_REQUEUE_REQ;
@ -591,20 +619,27 @@ twa_scsi_complete(struct twa_request *tr)
cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7],
cdb[8], cdb[9], cdb[10], cdb[11], cdb[12], cdb[13], cdb[14], cdb[15]);
cmd_hdr->err_specific_desc[sizeof(cmd_hdr->err_specific_desc) - 1] = '\0';
/*
* Print the error. Firmware doesn't yet support
* the 'Mode Sense' cmd. Don't print if the cmd
* is 'Mode Sense', and the error is 'Invalid field
* in CDB'.
*/
if (! ((cdb[0] == 0x1A) && (error == 0x10D)))
if (! ((cdb[0] == 0x1A) && (error == 0x10D))) {
u_int8_t *error_str =
&(cmd_hdr->err_desc[strlen(cmd_hdr->err_desc) + 1]);
if (error_str[0] == '\0')
error_str =
twa_find_msg_string(twa_error_table, error);
twa_printf(sc, "SCSI cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
cdb[0],
TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
error,
twa_find_msg_string(twa_error_table, error),
cmd_hdr->err_specific_desc);
error_str,
cmd_hdr->err_desc);
}
}
bcopy(cmd_hdr->sense_data, &(ccb->csio.sense_data),
@ -647,19 +682,29 @@ twa_drain_busy_queue(struct twa_softc *sc)
twa_unmap_request(tr);
if ((tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_INTERNAL) ||
(tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_IOCTL)) {
/* It's an internal/ioctl request. Simply free it. */
if (tr->tr_data)
free(tr->tr_data, M_DEVBUF);
/*
* It's an internal/ioctl request. The callback/
* originator should do the clean-up (except unmapping).
*/
tr->tr_error = EIO;
if (tr->tr_flags & TWA_CMD_SLEEP_ON_REQUEST) {
tr->tr_flags &= ~TWA_CMD_SLEEP_ON_REQUEST;
wakeup_one(tr);/* let the caller know */
}
else
if (tr->tr_callback)
tr->tr_callback(tr);
} else {
if ((ccb = tr->tr_private)) {
twa_unset_timer(tr);
/* It's a SCSI request. Complete it. */
ccb->ccb_h.status = CAM_SCSI_BUS_RESET |
CAM_RELEASE_SIMQ;
ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
twa_allow_new_requests(sc, ccb);
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
xpt_done(ccb);
}
twa_release_request(tr);
}
twa_release_request(tr);
}
}
@ -701,3 +746,47 @@ twa_disallow_new_requests(struct twa_softc *sc)
xpt_freeze_simq(sc->twa_sim, 1);
sc->twa_state |= TWA_STATE_SIMQ_FROZEN;
}
/*
* Function name: twa_set_timer
* Description: Set a timer to time a given request.
*
* Input: tr -- ptr to request pkt
* Output: None
* Return value: None
*/
void
twa_set_timer(struct twa_request *tr)
{
union ccb *ccb = (union ccb *)(tr->tr_private);
/* Set the timer only if external (CAM) request. */
if (ccb) {
tr->tr_flags |= TWA_CMD_TIMER_SET;
ccb->ccb_h.timeout_ch = timeout(twa_timeout, tr,
(ccb->ccb_h.timeout * hz) / 1000);
}
}
/*
* Function name: twa_unset_timer
* Description: Unset a previously set timer.
*
* Input: tr -- ptr to request pkt
* Output: None
* Return value: None
*/
void
twa_unset_timer(struct twa_request *tr)
{
union ccb *ccb = (union ccb *)(tr->tr_private);
if (tr->tr_flags & TWA_CMD_TIMER_SET) {
untimeout(twa_timeout, tr, ccb->ccb_h.timeout_ch);
tr->tr_flags &= ~TWA_CMD_TIMER_SET;
}
}

View file

@ -74,4 +74,6 @@ extern int twa_cam_setup(struct twa_softc *sc); /* attach to CAM */
extern void twa_cam_detach(struct twa_softc *sc); /* detach from CAM */
extern void twa_allow_new_requests(struct twa_softc *sc, void *ccb);/* unfreeze ccb flow from CAM */
extern void twa_disallow_new_requests(struct twa_softc *sc);/* freeze ccb flow from CAM */
extern void twa_set_timer(struct twa_request *tr); /* Set a timer to time a given request */
extern void twa_unset_timer(struct twa_request *tr);/* Unset a previously set timer */

View file

@ -146,7 +146,6 @@ static int twa_shutdown (device_t dev);
static int twa_suspend (device_t dev);
static int twa_resume (device_t dev);
static void twa_pci_intr(void *arg);
static void twa_intrhook (void *arg);
static device_method_t twa_methods[] = {
/* Device interface */
@ -262,6 +261,15 @@ twa_attach(device_t dev)
sc->twa_bus_tag = rman_get_bustag(sc->twa_io_res);
sc->twa_bus_handle = rman_get_bushandle(sc->twa_io_res);
/* Initialize the driver for this controller. */
if ((error = twa_setup(sc))) {
twa_free(sc);
return(error);
}
/* Print some information about the controller and configuration. */
twa_describe_controller(sc);
/* Allocate and connect our interrupt. */
res_id = 0;
if ((sc->twa_irq_res = bus_alloc_resource(sc->twa_bus_dev, SYS_RES_IRQ,
@ -278,35 +286,12 @@ twa_attach(device_t dev)
return(ENXIO);
}
/* Initialize the driver for this controller. */
if ((error = twa_setup(sc))) {
twa_free(sc);
return(error);
}
/* Print some information about the controller and configuration. */
twa_describe_controller(sc);
/* Create the control device. */
sc->twa_ctrl_dev = make_dev(&twa_cdevsw, device_get_unit(sc->twa_bus_dev),
UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR,
"twa%d", device_get_unit(sc->twa_bus_dev));
sc->twa_ctrl_dev->si_drv1 = sc;
/*
* Schedule ourselves to bring the controller up once interrupts are
* available. This isn't strictly necessary, since we disable
* interrupts while probing the controller, but it is more in keeping
* with common practice for other disk devices.
*/
sc->twa_ich.ich_func = twa_intrhook;
sc->twa_ich.ich_arg = sc;
if (config_intrhook_establish(&sc->twa_ich) != 0) {
twa_printf(sc, "Can't establish configuration hook.\n");
twa_free(sc);
return(ENXIO);
}
if ((error = twa_cam_setup(sc))) {
twa_free(sc);
return(error);
@ -336,22 +321,30 @@ twa_free(struct twa_softc *sc)
/* Destroy dma handles. */
bus_dmamap_unload(sc->twa_dma_tag, sc->twa_cmd_map);
bus_dmamap_unload(sc->twa_cmd_tag, sc->twa_cmd_map);
while ((tr = twa_dequeue_free(sc)) != NULL)
bus_dmamap_destroy(sc->twa_dma_tag, tr->tr_dma_map);
bus_dmamap_destroy(sc->twa_buf_tag, tr->tr_buf_map);
/* Free all memory allocated so far. */
if (sc->twa_req_buf)
free(sc->twa_req_buf, TWA_MALLOC_CLASS);
if (sc->twa_cmd_pkt_buf)
bus_dmamem_free(sc->twa_dma_tag, sc->twa_cmd_pkt_buf,
bus_dmamem_free(sc->twa_cmd_tag, sc->twa_cmd_pkt_buf,
sc->twa_cmd_map);
if (sc->twa_aen_queue[0])
free (sc->twa_aen_queue[0], M_DEVBUF);
free(sc->twa_aen_queue[0], M_DEVBUF);
/* Destroy the data-transfer DMA tag. */
if (sc->twa_dma_tag)
bus_dma_tag_destroy(sc->twa_dma_tag);
if (sc->twa_buf_tag)
bus_dma_tag_destroy(sc->twa_buf_tag);
/* Destroy the cmd DMA tag. */
if (sc->twa_cmd_tag)
bus_dma_tag_destroy(sc->twa_cmd_tag);
/* Destroy the parent DMA tag. */
if (sc->twa_parent_tag)
bus_dma_tag_destroy(sc->twa_parent_tag);
/* Disconnect the interrupt handler. */
if (sc->twa_intr_handle)
@ -516,30 +509,6 @@ twa_pci_intr(void *arg)
/*
* Function name: twa_intrhook
* Description: Callback for us to enable interrupts.
*
* Input: arg -- ptr to per ctlr structure
* Output: None
* Return value: None
*/
static void
twa_intrhook(void *arg)
{
struct twa_softc *sc = (struct twa_softc *)arg;
twa_dbg_dprint(4, sc, "twa_intrhook Entered");
/* Pull ourselves off the intrhook chain. */
config_intrhook_disestablish(&sc->twa_ich);
/* Enable interrupts. */
twa_enable_interrupts(sc);
}
/*
* Function name: twa_write_pci_config
* Description: Writes to the PCI config space.
@ -579,7 +548,7 @@ twa_alloc_req_pkts(struct twa_softc *sc, int num_reqs)
TWA_MALLOC_CLASS, M_NOWAIT)) == NULL)
return(ENOMEM);
/* Allocate the bus DMA tag appropriate for PCI. */
/* Create the parent dma tag. */
if (bus_dma_tag_create(NULL, /* parent */
TWA_ALIGNMENT, /* alignment */
0, /* boundary */
@ -591,20 +560,42 @@ twa_alloc_req_pkts(struct twa_softc *sc, int num_reqs)
TWA_MAX_SG_ELEMENTS, /* nsegments */
BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
BUS_DMA_ALLOCNOW, /* flags */
busdma_lock_mutex, /* lockfunc */
&Giant, /* lockfuncarg */
&sc->twa_dma_tag /* tag */)) {
twa_printf(sc, "Can't allocate DMA tag.\n");
NULL, /* lockfunc */
NULL, /* lockfuncarg */
&sc->twa_parent_tag /* tag */)) {
twa_printf(sc, "Can't allocate parent DMA tag.\n");
return(ENOMEM);
}
/* Allocate memory for cmd pkts. */
if (bus_dmamem_alloc(sc->twa_dma_tag,
(void *)(&(sc->twa_cmd_pkt_buf)),
BUS_DMA_WAITOK, &(sc->twa_cmd_map)))
/* Create a bus dma tag for cmd pkts. */
if (bus_dma_tag_create(sc->twa_parent_tag, /* parent */
TWA_ALIGNMENT, /* alignment */
0, /* boundary */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
TWA_Q_LENGTH *
(sizeof(struct twa_command_packet)),/* maxsize */
1, /* nsegments */
BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
0, /* flags */
NULL, /* lockfunc */
NULL, /* lockfuncarg */
&sc->twa_cmd_tag /* tag */)) {
twa_printf(sc, "Can't allocate cmd DMA tag.\n");
return(ENOMEM);
}
bus_dmamap_load(sc->twa_dma_tag, sc->twa_cmd_map,
/* Allocate memory for cmd pkts. */
if (bus_dmamem_alloc(sc->twa_cmd_tag,
(void *)(&(sc->twa_cmd_pkt_buf)),
BUS_DMA_WAITOK, &(sc->twa_cmd_map))) {
twa_printf(sc, "Can't allocate memory for cmd pkts.\n");
return(ENOMEM);
}
bus_dmamap_load(sc->twa_cmd_tag, sc->twa_cmd_map,
sc->twa_cmd_pkt_buf,
num_reqs * sizeof(struct twa_command_packet),
twa_setup_request_dmamap, sc, 0);
@ -612,6 +603,24 @@ twa_alloc_req_pkts(struct twa_softc *sc, int num_reqs)
bzero(sc->twa_cmd_pkt_buf,
num_reqs * sizeof(struct twa_command_packet));
/* Create a bus dma tag for data buffers. */
if (bus_dma_tag_create(sc->twa_parent_tag, /* parent */
TWA_ALIGNMENT, /* alignment */
0, /* boundary */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
TWA_MAX_IO_SIZE, /* maxsize */
TWA_MAX_SG_ELEMENTS, /* nsegments */
TWA_MAX_IO_SIZE, /* maxsegsize */
BUS_DMA_WAITOK, /* flags */
busdma_lock_mutex, /* lockfunc */
&Giant, /* lockfuncarg */
&sc->twa_buf_tag /* tag */)) {
twa_printf(sc, "Can't allocate buf DMA tag.\n");
return(ENOMEM);
}
for (i = 0; i < num_reqs; i++) {
tr = &(sc->twa_req_buf[i]);
tr->tr_command = &(sc->twa_cmd_pkt_buf[i]);
@ -621,15 +630,9 @@ twa_alloc_req_pkts(struct twa_softc *sc, int num_reqs)
tr->tr_sc = sc;
sc->twa_lookup[i] = tr;
/*
* Create a map for data buffers. maxsize (256 * 1024) used in
* bus_dma_tag_create above should suffice the bounce page needs
* for data buffers, since the max I/O size we support is 128KB.
* If we supported I/O's bigger than 256KB, we would have to
* create a second dma_tag, with the appropriate maxsize.
*/
if (bus_dmamap_create(sc->twa_dma_tag, 0,
&tr->tr_dma_map))
/* Create maps for data buffers. */
if (bus_dmamap_create(sc->twa_buf_tag, 0,
&tr->tr_buf_map))
return(ENOMEM);
/* Insert request into the free queue. */
@ -690,6 +693,7 @@ twa_setup_data_dmamap(void *arg, bus_dma_segment_t *segs,
twa_dbg_dprint_enter(10, tr->tr_sc);
tr->tr_flags |= TWA_CMD_MAPPED;
if ((tr->tr_flags & TWA_CMD_IN_PROGRESS) &&
(tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL))
twa_allow_new_requests(tr->tr_sc, (void *)(tr->tr_private));
@ -716,7 +720,7 @@ twa_setup_data_dmamap(void *arg, bus_dma_segment_t *segs,
}
if (tr->tr_flags & TWA_CMD_DATA_IN)
bus_dmamap_sync(tr->tr_sc->twa_dma_tag, tr->tr_dma_map,
bus_dmamap_sync(tr->tr_sc->twa_buf_tag, tr->tr_buf_map,
BUS_DMASYNC_PREREAD);
if (tr->tr_flags & TWA_CMD_DATA_OUT) {
/*
@ -725,7 +729,7 @@ twa_setup_data_dmamap(void *arg, bus_dma_segment_t *segs,
*/
if (tr->tr_flags & TWA_CMD_DATA_COPY_NEEDED)
bcopy(tr->tr_real_data, tr->tr_data, tr->tr_real_length);
bus_dmamap_sync(tr->tr_sc->twa_dma_tag, tr->tr_dma_map,
bus_dmamap_sync(tr->tr_sc->twa_buf_tag, tr->tr_buf_map,
BUS_DMASYNC_PREWRITE);
}
error = twa_submit_io(tr);
@ -819,14 +823,21 @@ twa_map_request(struct twa_request *tr)
/*
* Map the data buffer into bus space and build the s/g list.
*/
if ((error = bus_dmamap_load(sc->twa_dma_tag, tr->tr_dma_map,
tr->tr_data, tr->tr_length,
if ((error = bus_dmamap_load(sc->twa_buf_tag, tr->tr_buf_map,
tr->tr_data,
(bus_size_t)(tr->tr_length),
twa_setup_data_dmamap, tr,
BUS_DMA_WAITOK))) {
if (error == EINPROGRESS) {
tr->tr_flags |= TWA_CMD_IN_PROGRESS;
if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
twa_disallow_new_requests(sc);
int s;
s = splcam();
if (!(tr->tr_flags & TWA_CMD_MAPPED)) {
tr->tr_flags |= TWA_CMD_IN_PROGRESS;
if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
twa_disallow_new_requests(sc);
}
splx(s);
error = 0;
} else {
/* Free alignment buffer if it was used. */
@ -872,8 +883,8 @@ twa_unmap_request(struct twa_request *tr)
cmd_status = tr->tr_command->command.cmd_pkt_7k.generic.status;
if (tr->tr_flags & TWA_CMD_DATA_IN) {
bus_dmamap_sync(sc->twa_dma_tag,
tr->tr_dma_map, BUS_DMASYNC_POSTREAD);
bus_dmamap_sync(sc->twa_buf_tag,
tr->tr_buf_map, BUS_DMASYNC_POSTREAD);
/*
* If we are using a bounce buffer, and we are reading
@ -885,10 +896,10 @@ twa_unmap_request(struct twa_request *tr)
tr->tr_real_length);
}
if (tr->tr_flags & TWA_CMD_DATA_OUT)
bus_dmamap_sync(sc->twa_dma_tag, tr->tr_dma_map,
bus_dmamap_sync(sc->twa_buf_tag, tr->tr_buf_map,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->twa_dma_tag, tr->tr_dma_map);
bus_dmamap_unload(sc->twa_buf_tag, tr->tr_buf_map);
}
/* Free alignment buffer if it was used. */
@ -983,7 +994,6 @@ twa_print_request(struct twa_request *tr, int req_type)
struct twa_command_9k *cmd9k;
union twa_command_7k *cmd7k;
u_int8_t *cdb;
int cmd_phys_addr;
if (tr->tr_status != req_type) {
twa_printf(sc, "Invalid %s request %p in queue! req_type = %x, queue_type = %x\n",
@ -992,8 +1002,7 @@ twa_print_request(struct twa_request *tr, int req_type)
if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_9K) {
cmd9k = &(cmdpkt->command.cmd_pkt_9k);
cmd_phys_addr = cmd9k->sg_list[0].address;
twa_printf(sc, "9K cmd = %x %x %x %x %x %x %x %x %jx\n",
twa_printf(sc, "9K cmd = %x %x %x %x %x %x %x %jx %x\n",
cmd9k->command.opcode,
cmd9k->command.reserved,
cmd9k->unit,
@ -1001,8 +1010,8 @@ twa_print_request(struct twa_request *tr, int req_type)
cmd9k->status,
cmd9k->sgl_offset,
cmd9k->sgl_entries,
cmd_phys_addr,
(uintmax_t)cmd9k->sg_list[0].length);
(uintmax_t)(cmd9k->sg_list[0].address),
cmd9k->sg_list[0].length);
cdb = (u_int8_t *)(cmdpkt->command.cmd_pkt_9k.cdb);
twa_printf(sc, "cdb = %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7],
@ -1021,12 +1030,12 @@ twa_print_request(struct twa_request *tr, int req_type)
cmd7k->generic.count);
}
cmd_phys_addr = (int)(tr->tr_cmd_phys);
twa_printf(sc, "cmdphys=0x%x data=%p length=0x%jx\n",
cmd_phys_addr, tr->tr_data, (uintmax_t)tr->tr_length);
twa_printf(sc, "cmd_phys=0x%jx data=%p length=0x%x\n",
(uintmax_t)(tr->tr_cmd_phys), tr->tr_data,
tr->tr_length);
twa_printf(sc, "req_id=0x%x flags=0x%x callback=%p private=%p\n",
tr->tr_request_id, tr->tr_flags,
tr->tr_callback, tr->tr_private);
tr->tr_request_id, tr->tr_flags,
tr->tr_callback, tr->tr_private);
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -72,7 +72,7 @@ struct twa_message twa_aen_table[] = {
{0x0022, "Upgrade UDMA mode to higher speed"},
{0x0023, "Sector repair completed"},
{0x0024, "Sbuf memory test failed"},
{0x0025, "Error flushing cached write data to array"},
{0x0025, "Error flushing cached write data to disk"},
{0x0026, "Drive reported data ECC error"},
{0x0027, "DCB has checksum error"},
{0x0028, "DCB version is unsupported"},
@ -102,6 +102,37 @@ struct twa_message twa_aen_table[] = {
{0x0041, "Unit number assignments were lost"},
{0x0042, "Error during read of primary DCB"},
{0x0043, "Latent error found in backup DCB"},
{0x0044, "Voltage is within normal range"},
{0x0045, "Voltage is in low warning range"},
{0x0046, "Voltage is in high warning range"},
{0x0047, "Voltage is below operating range"},
{0x0048, "Voltage is above operating range"},
{0x0049, "Temperature is within normal range"},
{0x004A, "Temperature is in low warning range"},
{0x004B, "Temperature is high warning range"},
{0x004C, "Temperature is below operating range"},
{0x004D, "Temperature is above operating range"},
{0x004E, "Low current test started"},
{0x0050, "Low current test stopped"},
{0x0051, "High current test started"},
{0x0052, "High current test stopped"},
{0x0053, "Charge termination voltage is at high level"},
{0x0054, "Charge termination voltage is at high level"},
{0x0055, "Charge started"},
{0x0056, "Charge stopped"},
{0x0057, "Charge is in fault condition"},
{0x0058, "Capacity is below warning level"},
{0x0059, "Capacity is below error level"},
{0x005A, "Battery is present"},
{0x005B, "Battery is not present"},
{0x005C, "High current test is in warning level"},
{0x005D, "High current test is in fault level"},
{0x0060, "Bad cache meta data checksum"},
{0x0061, "Bad cache meta data signature"},
{0x0062, "Cache meta data restore failed"},
{0x0063, "Cache meta data was lost"},
{0x0064, "Cache write data sync failed"},
{0x0065, "Not able to sync cache write data"},
{0x00FC, "Recovered/finished array membership update"},
{0x00FD, "Handler lockup"},
{0x00FE, "Retrying PCI transfer"},
@ -147,15 +178,18 @@ struct twa_message twa_error_table[] = {
{0x0121, "Drive not degraded"},
{0x0122, "Reconstruct error"},
{0x0123, "Replace not accepted"},
{0x0124, "Replace drive capacity too small"},
{0x0124, "Drive capacity too small"},
{0x0125, "Sector count not allowed"},
{0x0126, "No spares left"},
{0x0127, "Reconstruct error"},
{0x0128, "Unit is offline"},
{0x0129, "Cannot update status to DCB"},
{0x012A, "Dchnl cannot be split"},
{0x012B, "Dchnl cannot be joined"},
{0x012C, "No migration recovery"},
{0x0130, "Invalid stripe handle"},
{0x0131, "Handle that was not locked"},
{0x0132, "Handle that was not empy"},
{0x0132, "Handle that was not empty"},
{0x0133, "Handle has different owner"},
{0x0140, "IPR has parent"},
{0x0150, "Illegal Pbuf address alignment"},
@ -184,6 +218,10 @@ struct twa_message twa_error_table[] = {
{0x01C7, "Flash file size error"},
{0x01C8, "Bad flash file checksum"},
{0x01CA, "Corrupt flash file system detected"},
{0x01CB, "Flash file has no component directory"},
{0x01CC, "Flash file component not found"},
{0x01CD, "Flash Write cycle Failed"},
{0x01CE, "Flash Erase cycle Failed"},
{0x01D0, "Invalid field in parameter list"},
{0x01D1, "Parameter list length error"},
{0x01D2, "Parameter item is not changeable"},
@ -200,8 +238,8 @@ struct twa_message twa_error_table[] = {
{0x0209, "Unclassified port error"},
{0x020A, "Drive aborted command"},
{0x0210, "Internal CRC error"},
{0x0211, "Host PCI bus abort"},
{0x0212, "Host PCI parity error"},
{0x0211, "PCI abort error"},
{0x0212, "PCI parity error"},
{0x0213, "Port handler error"},
{0x0214, "Token interrupt count error"},
{0x0215, "Timeout waiting for PCI transfer"},
@ -212,27 +250,63 @@ struct twa_message twa_error_table[] = {
{0x0232, "Binary image architecture incompatible"},
{0x0233, "Binary image has no signature"},
{0x0234, "Binary image has bad checksum"},
{0x0235, "Image downloaded overflowed buffer"},
{0x0235, "Binary image overflowed buffer"},
{0x0240, "I2C device not found"},
{0x0241, "I2C transaction aborted"},
{0x0242, "SO-DIMM parameter(s) incompatible using defaults"},
{0x0243, "SO-DIMM unsupported"},
{0x0244, "I2C clock is held low - Transfer aborted"},
{0x0245, "I2C data is held low - Transfer aborted"},
{0x0246, "I2C slave device NACKed the transfer"},
{0x0247, "I2C buffer in-sufficient"},
{0x0248, "SPI transfer status error"},
{0x0249, "SPI transfer timeout error"},
{0x0250, "Invalid unit descriptor size in CreateUnit"},
{0x0251, "Unit descriptor size exceeds data buffer in CreateUnit"},
{0x0252, "Invalid value in CreateUnit descriptor"},
{0x0253, "Inadequate disk space to support descriptor in CreateUnit"},
{0x0250, "Invalid unit descriptor size"},
{0x0251, "Unit descriptor size exceeds data buffer"},
{0x0252, "Invalid value in unit descriptor"},
{0x0253, "Inadequate disk space to support descriptor"},
{0x0254, "Unable to create data channel for this unit descriptor"},
{0x0255, "CreateUnit descriptor specifies a drive already in use"},
{0x0256, "Unable to write configuration to all disks during CreateUnit"},
{0x0257, "CreateUnit does not support this descriptor version"},
{0x0258, "Invalid subunit for RAID 0 or 5 in CreateUnit"},
{0x0259, "Too many descriptors in CreateUnit"},
{0x025A, "Invalid configuration specified in CreateUnit descriptor"},
{0x025B, "Invalid LBA offset specified in CreateUnit descriptor"},
{0x025C, "Invalid stripelet size specified in CreateUnit descriptor"},
{0x0257, "CreateUnit/MigrateUnit does not support this descriptor version"},
{0x0258, "Invalid subunit for RAID 0 or 5 in CreateUnit/MigrateUnit"},
{0x0259, "Too many descriptors in CreateUnit/MigrateUnit"},
{0x025A, "Invalid configuration specified in unit descriptor"},
{0x025B, "Invalid LBA offset specified in unit descriptor"},
{0x025C, "Invalid stripelet size specified in unit descriptor"},
{0x025D, "JBOD unit is not allowed"},
{0x0260, "SMART attribute exceeded threshold"},
{0x0270, "Unit is not in NORMAL state"},
{0x0271, "Invalid drive members"},
{0x0272, "Converted unit is not supported"},
{0x0300, "Internal errorcode (BBU base) - should not occur"},
{0x0301, "Invalid BBU state change request"},
{0x0302, "The BBU resource needed is in use ; retry command after a delay"},
{0x0303, "Command requires a battery pack to be present and enabled"},
{0x0310, "BBU command packet error"},
{0x0311, "BBU command not implemented"},
{0x0312, "BBU command buffer underflow"},
{0x0313, "BBU command buffer overflow"},
{0x0314, "BBU command incomplete"},
{0x0315, "BBU command checksum error"},
{0x0316, "BBU command timeout"},
{0x0320, "BBU parameter not defined"},
{0x0321, "BBU parameter size mismatch"},
{0x0322, "Cannot write a read-only BBU parameter"},
{0x0323, "BBU firmware version string not found"},
{0x0324, "BBU operating state not available"},
{0x0325, "BBU not present"},
{0x0326, "BBU not ready"},
{0x0327, "BBU S1 not compatible with HBA"},
{0x0328, "BBU S0 not compatible with HBA"},
{0x0329, "BBU not compatible with HBA"},
{0x032A, "BBU not in S0"},
{0x032B, "BBU not in S1"},
{0x032C, "Timeout on BBU power fail interrupt"},
{0x032D, "BBU command checksum error"},
{0x0330, "Log updates not allowed"},
{0x0331, "Logs are invalid"},
{0x0332, "Logs not found"},
{0xFFFFFFFF, (char *)NULL}
};

View file

@ -163,6 +163,7 @@
#define TWA_OP_DIAGNOSTICS 0x1F
/* Misc defines. */
#define TWA_BUNDLED_FW_VERSION_STRING "2.04.00.005"
#define TWA_ALIGNMENT 0x4
#define TWA_MAX_UNITS 16
#define TWA_INIT_MESSAGE_CREDITS 0x100
@ -170,12 +171,12 @@
#define TWA_64BIT_SG_ADDRESSES 0x00000001
#define TWA_EXTENDED_INIT_CONNECT 0x00000002
#define TWA_BASE_MODE 1
#define TWA_BASE_FW_SRL 0x17
#define TWA_BASE_FW_SRL 23
#define TWA_BASE_FW_BRANCH 0
#define TWA_BASE_FW_BUILD 1
#define TWA_CURRENT_FW_SRL 0x18
#define TWA_CURRENT_FW_BRANCH 1
#define TWA_CURRENT_FW_BUILD 9
#define TWA_CURRENT_FW_SRL 27
#define TWA_CURRENT_FW_BRANCH 2
#define TWA_CURRENT_FW_BUILD 6
#define TWA_9000_ARCH_ID 0x5 /* 9000 series controllers */
#define TWA_CTLR_FW_SAME_OR_NEWER 0x00000001
#define TWA_CTLR_FW_COMPATIBLE 0x00000002
@ -396,7 +397,7 @@ struct twa_command_header {
u_int8_t reserved:5;
} substatus_block;
} status_block;
u_int8_t err_specific_desc[98];
u_int8_t err_desc[98];
struct {
u_int8_t size_header;
u_int16_t reserved;