patch-2.4.15 linux/drivers/scsi/3w-xxxx.c

Next file: linux/drivers/scsi/3w-xxxx.h
Previous file: linux/drivers/sbus/char/su.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.14/linux/drivers/scsi/3w-xxxx.c linux/drivers/scsi/3w-xxxx.c
@@ -4,6 +4,7 @@
    Written By: Adam Radford <linux@3ware.com>
    Modifications By: Joel Jacobson <linux@3ware.com>
    		     Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+                     Brad Strand <linux@3ware.com>
 
    Copyright (C) 1999-2001 3ware Inc.
 
@@ -100,6 +101,11 @@
                  Fix possible null pointer dereference in tw_aen_drain_queue()
                  during initialization.
                  Clear pci parity errors during initialization and during io.
+   1.02.00.009 - Remove redundant increment in tw_state_request_start().
+                 Add ioctl support for direct ATA command passthru.
+                 Add entire aen code string list.
+   1.02.00.010 - Cleanup queueing code, fix jbod thoughput.
+                 Fix get_param for specific units.
 */
 
 #include <linux/module.h>
@@ -147,7 +153,7 @@
 };
 
 /* Globals */
-char *tw_driver_version="1.02.00.008";
+char *tw_driver_version="1.02.00.010";
 TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
 int tw_device_extension_count = 0;
 
@@ -169,23 +175,18 @@
 	dprintk(KERN_NOTICE "3w-xxxx: tw_aen_complete(): Queue'd code 0x%x\n", aen);
 
 	/* Print some useful info when certain aen codes come out */
-	switch (aen & 0x0ff) {
-		case TW_AEN_APORT_TIMEOUT:
-			printk(KERN_WARNING "3w-xxxx: scsi%d: Received drive timeout AEN on port %d, check drive and drive cables.\n", tw_dev->host->host_no,  aen >> 8);
-			break;
-		case TW_AEN_DRIVE_ERROR:
-			printk(KERN_WARNING "3w-xxxx: scsi%d: Received drive error AEN on port %d, check/replace cabling, or possible bad drive.\n", tw_dev->host->host_no, aen >> 8);
-			break;
-		case TW_AEN_SMART_FAIL:
-			printk(KERN_WARNING "3w-xxxx: scsi%d: Received S.M.A.R.T. threshold AEN on port %d, check drive/cooling, or possible bad drive.\n", tw_dev->host->host_no, aen >> 8);
-			break;
-		case TW_AEN_SBUF_FAIL:
-			printk(KERN_WARNING "3w-xxxx: scsi%d: Received SBUF integrity check failure AEN, reseat card or bad card.\n", tw_dev->host->host_no);
-			break;
-		default:
-			printk(KERN_WARNING "3w-xxxx: Received AEN 0x%x\n", aen);
+	if (aen == 0x0ff) {
+		printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: AEN queue overflow.\n", tw_dev->host->host_no);
+	} else {
+		if ((aen & 0x0ff) < TW_AEN_STRING_MAX) {
+			if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') {
+				printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s%d.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff], aen >> 8);
+			} else {
+				printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff]);
+			}
+		} else
+			printk(KERN_WARNING "3w-xxxx: scsi%d: Received AEN %d.\n", tw_dev->host->host_no, aen);
 	}
-
 	tw_dev->aen_count++;
 
 	/* Now queue the code */
@@ -235,7 +236,7 @@
 	response_que_addr = tw_dev->registers.response_que_addr;
 
 	if (tw_poll_status(tw_dev, TW_STATUS_ATTENTION_INTERRUPT, 15)) {
-		printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d.\n", tw_device_extension_count);
+		dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d.\n", tw_device_extension_count);
 		return 1;
 	}
 
@@ -291,7 +292,7 @@
 			mdelay(5);
 			status_reg_value = inl(status_reg_addr);
 			if (tw_check_bits(status_reg_value)) {
-				printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected bits.\n");
+				dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected bits.\n");
 				tw_decode_bits(tw_dev, status_reg_value);
 				return 1;
 			}
@@ -308,7 +309,8 @@
 				if (command_packet->status != 0) {
 					if (command_packet->flags != TW_AEN_TABLE_UNDEFINED) {
 						/* Bad response */
-						printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+						dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+						tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit);
 						return 1;
 					} else {
 						/* We know this is a 3w-1x00, and doesn't support aen's */
@@ -428,7 +430,7 @@
 
 	status_reg_value = inl(status_reg_addr);
 	if (tw_check_bits(status_reg_value)) {
-		printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n");
+		dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n");
 		tw_decode_bits(tw_dev, status_reg_value);
 		return 1;
 	}
@@ -525,11 +527,11 @@
 int tw_check_bits(u32 status_reg_value)
 {
 	if ((status_reg_value & TW_STATUS_EXPECTED_BITS) != TW_STATUS_EXPECTED_BITS) {  
-		printk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits (0x%x).\n", status_reg_value);
+		dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits (0x%x).\n", status_reg_value);
 		return 1;
 	}
 	if ((status_reg_value & TW_STATUS_UNEXPECTED_BITS) != 0) {
-		printk(KERN_WARNING "3w-xxxx: tw_check_bits(): Found unexpected bits (0x%x).\n", status_reg_value);
+		dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): Found unexpected bits (0x%x).\n", status_reg_value);
 		return 1;
 	}
 
@@ -633,8 +635,12 @@
 		case 0x51:
 			printk(KERN_WARNING "3w-xxxx: scsi%d: Unrecoverable drive error on unit %d, check/replace cabling, or possible bad drive.\n", tw_dev->host->host_no, unit);
 			break;
+		default:
+			printk(KERN_WARNING "3w-xxxx: scsi%d: Controller error: status = 0x%x, flags = 0x%x, unit #%d.\n", tw_dev->host->host_no, status, flags, unit);
 		}
 		break;
+	default:
+		printk(KERN_WARNING "3w-xxxx: scsi%d: Controller error: status = 0x%x, flags = 0x%x, unit #%d.\n", tw_dev->host->host_no, status, flags, unit);
 	}
 } /* End tw_decode_error() */
 
@@ -660,7 +666,7 @@
 	status_reg_value = inl(status_reg_addr);
 
 	if (tw_check_bits(status_reg_value)) {
-		printk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 1.\n");
+		dprintk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 1.\n");
 		tw_decode_bits(tw_dev, status_reg_value);
 		return 1;
 	}
@@ -669,7 +675,7 @@
 		response_que_value = inl(response_que_addr);
 		status_reg_value = inl(status_reg_addr);
 		if (tw_check_bits(status_reg_value)) {
-			printk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 2.\n");
+			dprintk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 2.\n");
 			tw_decode_bits(tw_dev, status_reg_value);
 			return 1;
 		}
@@ -817,9 +823,20 @@
 				continue;
 			}
 
-			/* Calculate max cmds per lun */
-			if (tw_dev->num_units > 0)
-				tw_host->cmd_per_lun = (TW_Q_LENGTH-2)/tw_dev->num_units;
+			/* Calculate max cmds per lun, and setup queues */
+			if (tw_dev->num_units > 0) {
+				if ((tw_dev->num_raid_five > 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) {
+					tw_host->cmd_per_lun = (TW_MAX_BOUNCEBUF-1)/tw_dev->num_units;
+					tw_dev->free_head = TW_Q_START;
+					tw_dev->free_tail = TW_MAX_BOUNCEBUF - 1;
+					tw_dev->free_wrap = TW_MAX_BOUNCEBUF - 1;
+				} else {
+					tw_host->cmd_per_lun = (TW_Q_LENGTH-1)/tw_dev->num_units;
+					tw_dev->free_head = TW_Q_START;
+					tw_dev->free_tail = TW_Q_LENGTH - 1;
+					tw_dev->free_wrap = TW_Q_LENGTH - 1;
+				}
+			}
 
 		/* Register the card with the kernel SCSI layer */
 			host = scsi_register(tw_host, sizeof(TW_Device_Extension));
@@ -889,7 +906,7 @@
 	}
 
 	if (numcards == 0) 
-		printk(KERN_WARNING "3w-xxxx: tw_findcards(): No cards found.\n");
+		printk(KERN_WARNING "3w-xxxx: No cards with valid units found.\n");
 	else
 	  register_reboot_notifier(&tw_notifier);
 
@@ -899,18 +916,19 @@
 /* This function will free up device extension resources */
 void tw_free_device_extension(TW_Device_Extension *tw_dev)
 {
-	int i, imax;
-	imax = TW_Q_LENGTH;
+	int i;
 
 	dprintk(KERN_NOTICE "3w-xxxx: tw_free_device_extension()\n");
 	/* Free command packet and generic buffer memory */
-	for (i=0;i<imax;i++) {
+	for (i=0;i<TW_Q_LENGTH;i++) {
 		if (tw_dev->command_packet_virtual_address[i]) 
 			kfree(tw_dev->command_packet_virtual_address[i]);
 
 		if (tw_dev->alignment_virtual_address[i])
 			kfree(tw_dev->alignment_virtual_address[i]);
 
+	}
+	for (i=0;i<TW_MAX_BOUNCEBUF;i++) {
 		if (tw_dev->bounce_buffer[i])
 			kfree(tw_dev->bounce_buffer[i]);
 	}
@@ -922,7 +940,7 @@
 	int i;
 
 	for (i=0;i<tw_device_extension_count;i++) {
-		printk(KERN_NOTICE "3w-xxxx: Notifying card #%d\n", i);
+		printk(KERN_NOTICE "3w-xxxx: Shutting down card %d.\n", i);
 		tw_shutdown_device(tw_device_extension_list[i]);
 	}
 	unregister_reboot_notifier(&tw_notifier);
@@ -981,7 +999,7 @@
 		mdelay(5);
 		status_reg_value = inl(status_reg_addr);
 		if (tw_check_bits(status_reg_value)) {
-			printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected bits.\n");
+			dprintk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected bits.\n");
 			tw_decode_bits(tw_dev, status_reg_value);
 			return 1;
 		}
@@ -995,7 +1013,8 @@
 			}
 			if (command_packet->status != 0) {
 				/* bad response */
-				printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+				dprintk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+				tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit);
 				return 1;
 			}
 			break;	/* Response was okay, so we exit */
@@ -1043,8 +1062,6 @@
 	tw_dev->num_units = 0;
 	tw_dev->num_aborts = 0;
 	tw_dev->num_resets = 0;
-	tw_dev->free_head = TW_Q_START;
-	tw_dev->free_tail = TW_Q_LENGTH - 1;
 	tw_dev->posted_request_count = 0;
 	tw_dev->max_posted_request_count = 0;
 	tw_dev->max_sgl_entries = 0;
@@ -1135,7 +1152,7 @@
 		mdelay(5);
 		status_reg_value = inl(status_reg_addr);
 		if (tw_check_bits(status_reg_value)) {
-			printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n");
+			dprintk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n");
 			tw_decode_bits(tw_dev, status_reg_value);
 			return 1;
 		}
@@ -1149,7 +1166,8 @@
 			}
 			if (command_packet->status != 0) {
 				/* bad response */
-				printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+				dprintk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+				tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit);
 				return 1;
 			}
 			found = 1;
@@ -1181,7 +1199,7 @@
 	tw_dev->num_units = num_units;
 
 	if (num_units == 0) {
-		printk(KERN_NOTICE "3w-xxxx: tw_initialize_units(): No units found.\n");
+		dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_units(): No units found.\n");
 		return 1;
 	}
 
@@ -1238,7 +1256,7 @@
 			mdelay(5);
 			status_reg_value = inl(status_reg_addr);
 			if (tw_check_bits(status_reg_value)) {
-				printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n");
+				dprintk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n");
 				tw_decode_bits(tw_dev, status_reg_value);
 				return 1;
 			}
@@ -1252,7 +1270,8 @@
 				}
 				if (command_packet->status != 0) {
 					/* bad response */
-					printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+					dprintk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+					tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit);
 					return 1;
 				}
 				found = 1;
@@ -1277,10 +1296,10 @@
 
 	/* Now allocate raid5 bounce buffers */
 	if ((num_raid_five != 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) {
-		for (i=0;i<TW_Q_LENGTH;i++) {
+		for (i=0;i<TW_MAX_BOUNCEBUF;i++) {
 			tw_allocate_memory(tw_dev, i, sizeof(TW_Sector)*TW_MAX_SECTORS, 2);
 			if (tw_dev->bounce_buffer[i] == NULL) {
-				printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bounce buffer allocation failed.\n");
+				printk(KERN_WARNING "3w-xxxx: Bounce buffer allocation failed.\n");
 				return 1;
 			}
 			memset(tw_dev->bounce_buffer[i], 0, sizeof(TW_Sector)*TW_MAX_SECTORS);
@@ -1342,7 +1361,7 @@
 			tw_state_request_start(tw_dev, &request_id);
 			error = tw_aen_read_queue(tw_dev, request_id);
 			if (error) {
-				printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Error reading aen queue.\n");
+				printk(KERN_WARNING "3w-xxxx: scsi%d: Error reading aen queue.\n", tw_dev->host->host_no);
 				tw_dev->state[request_id] = TW_S_COMPLETED;
 				tw_state_request_finish(tw_dev, request_id);
 			}
@@ -1354,7 +1373,7 @@
 			while (tw_dev->pending_request_count > 0) {
 				request_id = tw_dev->pending_queue[tw_dev->pending_head];
 				if (tw_dev->state[request_id] != TW_S_PENDING) {
-					printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found request id that wasn't pending.\n");
+					printk(KERN_WARNING "3w-xxxx: scsi%d: Found request id that wasn't pending.\n", tw_dev->host->host_no);
 					break;
 				}
 				if (tw_post_command_packet(tw_dev, request_id)==0) {
@@ -1382,12 +1401,12 @@
 				command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
 				error = 0;
 				if (command_packet->status != 0) {
-					printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Bad response, status = 0x%x, flags = 0x%x, unit = 0x%x.\n", command_packet->status, command_packet->flags, command_packet->byte3.unit);
+					dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Bad response, status = 0x%x, flags = 0x%x, unit = 0x%x.\n", command_packet->status, command_packet->flags, command_packet->byte3.unit);
 					tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit);
 					error = 1;
 				}
 				if (tw_dev->state[request_id] != TW_S_POSTED) {
-					printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", request_id, command_packet->byte0.opcode);
+					printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", tw_dev->host->host_no, request_id, command_packet->byte0.opcode);
 					error = 1;
 				}
 				if (TW_STATUS_ERRORS(status_reg_value)) {
@@ -1400,24 +1419,22 @@
 					dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n");
 					error = tw_aen_complete(tw_dev, request_id);
 					if (error) {
-						printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Error completing aen.\n");
+						printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no);
 					}
 					status_reg_value = inl(status_reg_addr);
 					if (tw_check_bits(status_reg_value)) {
-						printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
+						dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
 						tw_decode_bits(tw_dev, status_reg_value);
 					}
 		} else {
 				switch (tw_dev->srb[request_id]->cmnd[0]) {
 					case READ_10:
-						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10\n");
 					case READ_6:
-						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_6\n");
+						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10/READ_6\n");
 						break;
 					case WRITE_10:
-						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10\n");
 					case WRITE_6:
-						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_6\n");
+						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10/WRITE_6\n");
 						break;
 					case INQUIRY:
 						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught INQUIRY\n");
@@ -1432,7 +1449,7 @@
 						error = tw_ioctl_complete(tw_dev, request_id);
 						break;
 					default:
-						printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unknown scsi opcode: 0x%x.\n", tw_dev->srb[request_id]->cmnd[0]);
+						printk(KERN_WARNING "3w-xxxx: scsi%d: Unknown scsi opcode: 0x%x.\n", tw_dev->host->host_no, tw_dev->srb[request_id]->cmnd[0]);
 						tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16);
 						tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
 					}
@@ -1450,7 +1467,7 @@
 					tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
 					status_reg_value = inl(status_reg_addr);
 					if (tw_check_bits(status_reg_value)) {
-						printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
+						dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
 						tw_decode_bits(tw_dev, status_reg_value);
 					}
 				}
@@ -1471,6 +1488,7 @@
 	TW_Command *command_packet;
 	u32 param_value;
 	TW_Ioctl *ioctl = NULL;
+	TW_Passthru *passthru = NULL;
 	int tw_aen_code;
 
 	ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer;
@@ -1519,6 +1537,7 @@
 		case TW_OP_GET_PARAM:
 			dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_GET_PARAM.\n");
 			command_packet->byte0.opcode = TW_OP_GET_PARAM;
+			command_packet->byte3.unit = ioctl->unit_index;
 			param->table_id = ioctl->table_id;
 			param->parameter_id = ioctl->parameter_id;
 			param->parameter_size_bytes = ioctl->parameter_size_bytes;
@@ -1562,7 +1581,26 @@
 			tw_dev->srb[request_id]->result = (DID_OK << 16);
 			tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
 			return 0;
-	        case TW_CMD_PACKET:
+		case TW_ATA_PASSTHRU:
+			if (ioctl->data != NULL) {
+				memcpy(command_packet, ioctl->data, sizeof(TW_Command));
+				command_packet->request_id = request_id;
+			} else {
+				printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n");
+				return 1;
+			}
+
+			passthru = (TW_Passthru *)tw_dev->command_packet_virtual_address[request_id];
+			passthru->sg_list[0].length = passthru->sector_count*512;
+			if (passthru->sg_list[0].length > TW_MAX_PASSTHRU_BYTES) {
+				printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Passthru size (%ld) too big.\n", passthru->sg_list[0].length);
+				return 1;
+			}
+			passthru->sg_list[0].address = virt_to_bus(tw_dev->alignment_virtual_address[request_id]);
+			tw_post_command_packet(tw_dev, request_id);
+			return 0;
+		case TW_CMD_PACKET:
+			dprintk(KERN_WARNING "3w-xxxx: tw_ioctl(): caught TW_CMD_PACKET.\n");
 			if (ioctl->data != NULL) {
 				memcpy(command_packet, ioctl->data, sizeof(TW_Command));
 				command_packet->request_id = request_id;
@@ -1596,7 +1634,6 @@
 	command_packet->byte0.sgl_offset = 2;
 	command_packet->size = 4;
 	command_packet->request_id = request_id;
-	command_packet->byte3.unit = 0;
 	command_packet->byte3.host_id = 0;
 	command_packet->status = 0;
 	command_packet->flags = 0;
@@ -1614,7 +1651,10 @@
 	unsigned char *param_data;
 	unsigned char *buff;
 	TW_Param *param;
+	TW_Ioctl *ioctl = NULL;
+	TW_Passthru *passthru = NULL;
 
+	ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer;
 	dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete()\n");
 	buff = tw_dev->srb[request_id]->request_buffer;
 	if (buff == NULL) {
@@ -1622,16 +1662,23 @@
 		return 1;
 	}
 	dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete(): Request_bufflen = %d\n", tw_dev->srb[request_id]->request_bufflen);
-	memset(buff, 0, tw_dev->srb[request_id]->request_bufflen);
-	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
-	if (param == NULL) {
-		printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n");
-		return 1;
-	}
-	param_data = &(param->data[0]);
-
-	memcpy(buff, param_data, tw_dev->ioctl_size[request_id]);
 
+	ioctl = (TW_Ioctl *)buff;
+	switch (ioctl->opcode) {
+		case TW_ATA_PASSTHRU:
+			passthru = (TW_Passthru *)ioctl->data;
+			memcpy(buff, tw_dev->alignment_virtual_address[request_id], passthru->sector_count * 512);
+			break;
+		default:
+			memset(buff, 0, tw_dev->srb[request_id]->request_bufflen);
+			param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
+			if (param == NULL) {
+				printk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): Bad alignment virtual address.\n");
+				return 1;
+			}
+			param_data = &(param->data[0]);
+			memcpy(buff, param_data, tw_dev->ioctl_size[request_id]);
+	}
 	return 0;
 } /* End tw_ioctl_complete() */
 
@@ -1659,7 +1706,7 @@
 		status_reg_value = inl(status_reg_addr);
 		do_gettimeofday(&timeout);
 		if (before.tv_sec + seconds < timeout.tv_sec) { 
-			printk(KERN_WARNING "3w-xxxx: tw_poll_status(): Flag 0x%x not found.\n", flag);
+			dprintk(KERN_WARNING "3w-xxxx: tw_poll_status(): Flag 0x%x not found.\n", flag);
 			return 1;
 		}
 		mdelay(1);
@@ -1680,7 +1727,7 @@
 	status_reg_value = inl(status_reg_addr);
 
 	if (tw_check_bits(status_reg_value)) {
-		printk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n");
+		dprintk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n");
 		tw_decode_bits(tw_dev, status_reg_value);
 	}
 
@@ -1724,7 +1771,7 @@
 	imax = TW_Q_LENGTH;
 
 	if (tw_reset_sequence(tw_dev)) {
-		printk(KERN_WARNING "3w-xxxx: tw_reset_device_extension(): Reset sequence failed for card %d.\n", tw_dev->host->host_no);
+		printk(KERN_WARNING "3w-xxxx: scsi%d: Reset sequence failed.\n", tw_dev->host->host_no);
 		return 1;
 	}
 
@@ -1772,14 +1819,14 @@
 
 		error = tw_aen_drain_queue(tw_dev);
 		if (error) {
-			printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): No attention interrupt for card %d.\n", tw_dev->host->host_no);
+			printk(KERN_WARNING "3w-xxxx: scsi%d: Card not responding, retrying.\n", tw_dev->host->host_no);
 			tries++;
 			continue;
 		}
 
 		/* Check for controller errors */
 		if (tw_check_errors(tw_dev)) {
-			printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Controller errors found, soft resetting card %d.\n", tw_dev->host->host_no);
+			printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors found, retrying.\n", tw_dev->host->host_no);
 			tries++;
 			continue;
 		}
@@ -1787,7 +1834,7 @@
 		/* Empty the response queue again */
 		error = tw_empty_response_que(tw_dev);
 		if (error) {
-			printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Couldn't empty response queue for card %d.\n", tw_dev->host->host_no);
+			printk(KERN_WARNING "3w-xxxx: scsi%d: Couldn't empty response queue, retrying.\n", tw_dev->host->host_no);
 			tries++;
 			continue;
 		}
@@ -1797,13 +1844,13 @@
 	}
 
 	if (tries >= TW_MAX_RESET_TRIES) {
-		printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Controller error or no attention interrupt: giving up for card %d.\n", tw_dev->host->host_no);
+		printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors, card not responding, check all cabling.\n", tw_dev->host->host_no);
 		return 1;
 	}
 
 	error = tw_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS);
 	if (error) {
-		printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Couldn't initconnection for card %d.\n", tw_dev->host->host_no);
+		printk(KERN_WARNING "3w-xxxx: scsi%d: Connection initialization failed.\n", tw_dev->host->host_no);
 		return 1;
 	}
 
@@ -1893,14 +1940,14 @@
 	for (i=0;i<TW_Q_LENGTH;i++) {
 		if (tw_dev->srb[i] == SCpnt) {
 			if (tw_dev->state[i] == TW_S_STARTED) {
-				printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Abort succeeded for started Scsi_Cmnd 0x%x\n", (u32)tw_dev->srb[i]);
+				printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out.\n", tw_dev->host->host_no, (u32)SCpnt);
 				tw_dev->state[i] = TW_S_COMPLETED;
 				tw_state_request_finish(tw_dev, i);
 				spin_unlock(&tw_dev->tw_lock);
 				return (SUCCESS);
 			}
 			if (tw_dev->state[i] == TW_S_PENDING) {
-				printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Abort succeeded for pending Scsi_Cmnd 0x%x\n", (u32)tw_dev->srb[i]);
+				printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out.\n", tw_dev->host->host_no, (u32)SCpnt);
 				if (tw_dev->pending_head == TW_Q_LENGTH-1) {
 					tw_dev->pending_head = TW_Q_START;
 				} else {
@@ -1916,10 +1963,9 @@
 	}
 
 	/* If the command has already been posted, we have to reset the card */
-	printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Abort failed for unknown Scsi_Cmnd 0x%x, resetting card %d.\n", (u32)SCpnt, tw_dev->host->host_no);
-
+	printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, (u32)SCpnt);
 	if (tw_reset_device_extension(tw_dev)) {
-		printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Reset failed for card %d.\n", tw_dev->host->host_no);
+		dprintk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Reset failed for card %d.\n", tw_dev->host->host_no);
 		spin_unlock(&tw_dev->tw_lock);
 		return (FAILED);
 	}
@@ -1956,11 +2002,11 @@
 
 	/* Now reset the card and some of the device extension data */
 	if (tw_reset_device_extension(tw_dev)) {
-		printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Reset failed for card %d.\n", tw_dev->host->host_no);
+		printk(KERN_WARNING "3w-xxxx: scsi%d: Reset failed.\n", tw_dev->host->host_no);
 		spin_unlock(&tw_dev->tw_lock);
 		return (FAILED);
 	}
-	printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Reset succeeded for card %d.\n", tw_dev->host->host_no);
+	printk(KERN_WARNING "3w-xxxx: scsi%d: Reset succeeded.\n", tw_dev->host->host_no);
 	spin_unlock(&tw_dev->tw_lock);
 
 	return (SUCCESS);
@@ -2073,13 +2119,10 @@
 
 	switch (*command) {
 		case READ_10:
-			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_10.\n");
 		case READ_6:
-			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_6.\n");
 		case WRITE_10:
-			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught WRITE_10.\n");
 		case WRITE_6:
-			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught WRITE_6.\n");
+			dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ/WRITE.\n");
 			error = tw_scsiop_read_write(tw_dev, request_id);
 			break;
 		case TEST_UNIT_READY:
@@ -2103,7 +2146,7 @@
 			error = tw_ioctl(tw_dev, request_id);
 			break;
 		default:
-			printk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): Unknown scsi opcode: 0x%x\n", *command);
+			printk(KERN_NOTICE "3w-xxxx: scsi%d: Unknown scsi opcode: 0x%x\n", tw_dev->host->host_no, *command);
 			tw_dev->state[request_id] = TW_S_COMPLETED;
 			tw_state_request_finish(tw_dev, request_id);
 			SCpnt->result = (DID_BAD_TARGET << 16);
@@ -2569,7 +2612,7 @@
 		mdelay(5);
 		status_reg_value = inl(status_reg_addr);
 		if (tw_check_bits(status_reg_value)) {
-			printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected bits.\n");
+			dprintk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected bits.\n");
 			tw_decode_bits(tw_dev, status_reg_value);
 			return 1;
 		}
@@ -2583,7 +2626,8 @@
 			}
 			if (command_packet->status != 0) {
 				/* bad response */
-				printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+				dprintk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);
+				tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit);
 				return 1;
 			}
 			break; /* Response was okay, so we exit */
@@ -2603,7 +2647,7 @@
 	error = request_irq(tw_dev->tw_pci_dev->irq, tw_interrupt, SA_SHIRQ, device, tw_dev);
 
 	if (error < 0) {
-		printk(KERN_WARNING "3w-xxxx: tw_setup_irq(): Error requesting IRQ: %d for card %d.\n", tw_dev->tw_pci_dev->irq, tw_dev->host->host_no);
+		printk(KERN_WARNING "3w-xxxx: scsi%d: Error requesting IRQ: %d.\n", tw_dev->host->host_no, tw_dev->tw_pci_dev->irq);
 		return 1;
 	}
 	return 0;
@@ -2621,9 +2665,9 @@
 	/* poke the board */
 	error = tw_initconnection(tw_dev, 1);
 	if (error) {
-		printk(KERN_WARNING "3w-xxxx: tw_shutdown_device(): Couldn't initconnection for card %d.\n", tw_dev->host->host_no);
+		printk(KERN_WARNING "3w-xxxx: scsi%d: Connection shutdown failed.\n", tw_dev->host->host_no);
 	} else {
-		printk(KERN_NOTICE "3w-xxxx shutdown succeeded\n");
+		printk(KERN_NOTICE "3w-xxxx: Shutdown complete.\n");
 	}
 
 	/* Re-enable interrupts */
@@ -2654,7 +2698,7 @@
 	dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_finish()\n");
   
 	do {    
-		if (tw_dev->free_tail == TW_Q_LENGTH-1) {
+		if (tw_dev->free_tail == tw_dev->free_wrap) {
 			tw_dev->free_tail = TW_Q_START;
 		} else {
 			tw_dev->free_tail = tw_dev->free_tail + 1;
@@ -2678,23 +2722,14 @@
 
 	/* Obtain next free request_id */
 	do {
-		if (tw_dev->free_head == TW_Q_LENGTH - 1) {
+		if (tw_dev->free_head == tw_dev->free_wrap) {
 			tw_dev->free_head = TW_Q_START;
 		} else {
 			tw_dev->free_head = tw_dev->free_head + 1;
 		}
-	} while ((tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_STARTED) ||
-		 (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_POSTED) ||
-		 (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_PENDING) ||
-		 (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_COMPLETED));
+	} while (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] & TW_START_MASK);
 
 	id = tw_dev->free_queue[tw_dev->free_head];
-
-	if (tw_dev->free_head == TW_Q_LENGTH - 1) {
-		tw_dev->free_head = TW_Q_START;
-	} else {
-		tw_dev->free_head = tw_dev->free_head + 1;
-	}
 
 	dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_start(): id = %d.\n", id);
 	*request_id = id;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)