2 3w-xxxx.c -- 3ware Storage Controller device driver for Linux.
4 Written By: Adam Radford <linux@3ware.com>
5 Copyright (C) 1999-2000 3ware Inc.
7 Kernel compatablity By: Andre Hedrick <andre@suse.com>
8 Non-Copyright (C) 2000 Andre Hedrick <andre@suse.com>
10 Further tiny build fixes and trivial hoovering Alan Cox
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; version 2 of the License.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
22 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26 solely responsible for determining the appropriateness of using and
27 distributing the Program and assumes all risks associated with its
28 exercise of rights under this Agreement, including but not limited to
29 the risks and costs of program errors, damage to or loss of data,
30 programs or equipment, and unavailability or interruption of operations.
32 DISCLAIMER OF LIABILITY
33 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
41 You should have received a copy of the GNU General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
45 Bugs/Comments/Suggestions should be mailed to:
48 For more information, goto:
52 #include <linux/module.h>
54 MODULE_AUTHOR ("3ware Inc.");
55 MODULE_DESCRIPTION ("3ware Storage Controller Linux Driver");
57 #include <linux/kernel.h>
58 #include <linux/pci.h>
59 #include <linux/time.h>
60 #include <linux/proc_fs.h>
61 #include <linux/sched.h>
62 #include <linux/ioport.h>
63 #include <linux/blk.h>
64 #include <linux/hdreg.h>
65 #include <linux/string.h>
66 #include <linux/delay.h>
67 #include <linux/smp.h>
68 #include <linux/spinlock.h>
70 #include <asm/errno.h>
73 #include <asm/uaccess.h>
75 #define __3W_C /* let 3w-xxxx.h know it is use */
83 static int tw_copy_info(TW_Info
*info
, char *fmt
, ...);
84 static void tw_copy_mem_info(TW_Info
*info
, char *data
, int len
);
85 static void tw_interrupt(int irq
, void *dev_instance
, struct pt_regs
*regs
);
88 char *tw_driver_version
="1.0.000";
89 TW_Device_Extension
*tw_device_extension_list
[TW_MAX_SLOT
];
90 int tw_device_extension_count
= 0;
94 /* This function will complete an aen request from the isr */
95 int tw_aen_complete(TW_Device_Extension
*tw_dev
, int request_id
)
98 unsigned short aen
, aen_code
;
100 if (tw_dev
->alignment_virtual_address
[request_id
] == NULL
) {
101 printk(KERN_WARNING
"3w-xxxx: tw_aen_complete(): Bad alignment virtual address.\n");
104 param
= (TW_Param
*)tw_dev
->alignment_virtual_address
[request_id
];
105 aen
= *(unsigned short *)(param
->data
);
106 aen_code
= (aen
& 0x0ff);
107 dprintk(KERN_NOTICE
"3w-xxxx: tw_aen_complete(): Queue'd code 0x%x\n", aen_code
);
108 /* Now queue the code */
109 tw_dev
->aen_queue
[tw_dev
->aen_tail
] = aen_code
;
110 if (tw_dev
->aen_tail
== TW_Q_LENGTH
- 1) {
111 tw_dev
->aen_tail
= TW_Q_START
;
113 tw_dev
->aen_tail
= tw_dev
->aen_tail
+ 1;
115 if (tw_dev
->aen_head
== tw_dev
->aen_tail
) {
116 if (tw_dev
->aen_head
== TW_Q_LENGTH
- 1) {
117 tw_dev
->aen_head
= TW_Q_START
;
119 tw_dev
->aen_head
= tw_dev
->aen_head
+ 1;
122 tw_dev
->state
[request_id
] = TW_S_COMPLETED
;
123 tw_state_request_finish(tw_dev
, request_id
);
126 } /* End tw_aen_complete() */
128 /* This function will drain the aen queue after a soft reset */
129 int tw_aen_drain_queue(TW_Device_Extension
*tw_dev
)
131 TW_Command
*command_packet
;
135 u32 command_que_value
= 0, command_que_addr
;
136 u32 status_reg_value
= 0, status_reg_addr
;
138 TW_Response_Queue response_queue
;
139 u32 response_que_addr
;
141 unsigned short aen_code
;
148 dprintk(KERN_NOTICE
"3w-xxxx: tw_aen_drain_queue()\n");
150 command_que_addr
= tw_dev
->registers
.command_que_addr
;
151 status_reg_addr
= tw_dev
->registers
.status_reg_addr
;
152 response_que_addr
= tw_dev
->registers
.response_que_addr
;
154 if (tw_poll_status(tw_dev
, TW_STATUS_ATTENTION_INTERRUPT
, 15)) {
155 printk(KERN_WARNING
"3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d\n", tw_dev
->host
->host_no
);
159 /* Initialize command packet */
160 if (tw_dev
->command_packet_virtual_address
[request_id
] == NULL
) {
161 printk(KERN_WARNING
"3w-xxxx: tw_aen_drain_queue(): Bad command packet virtual address.\n");
164 command_packet
= (TW_Command
*)tw_dev
->command_packet_virtual_address
[request_id
];
165 memset(command_packet
, 0, sizeof(TW_Sector
));
166 command_packet
->byte0
.opcode
= TW_OP_GET_PARAM
;
167 command_packet
->byte0
.sgl_offset
= 2;
168 command_packet
->size
= 4;
169 command_packet
->request_id
= request_id
;
170 command_packet
->byte3
.unit
= 0;
171 command_packet
->byte3
.host_id
= 0;
172 command_packet
->status
= 0;
173 command_packet
->flags
= 0;
174 command_packet
->byte6
.parameter_count
= 1;
175 command_que_value
= tw_dev
->command_packet_physical_address
[request_id
];
176 if (command_que_value
== 0) {
177 printk(KERN_WARNING
"3w-xxxx: tw_aen_drain_queue(): Bad command packet physical address.\n");
181 /* Now setup the param */
182 if (tw_dev
->alignment_virtual_address
[request_id
] == NULL
) {
183 printk(KERN_WARNING
"3w-xxxx: tw_aen_drain_queue(): Bad alignment virtual address.\n");
186 param
= (TW_Param
*)tw_dev
->alignment_virtual_address
[request_id
];
187 memset(param
, 0, sizeof(TW_Sector
));
188 param
->table_id
= 0x401; /* AEN table */
189 param
->parameter_id
= 2; /* Unit code */
190 param
->parameter_size_bytes
= 2;
191 param_value
= tw_dev
->alignment_physical_address
[request_id
];
192 if (param_value
== 0) {
193 printk(KERN_WARNING
"3w-xxxx: tw_aen_drain_queue(): Bad alignment physical address.\n");
196 command_packet
->byte8
.param
.sgl
[0].address
= param_value
;
197 command_packet
->byte8
.param
.sgl
[0].length
= sizeof(TW_Sector
);
199 imax
= TW_POLL_MAX_RETRIES
;
201 /* Now drain the controller's aen queue */
203 /* Post command packet */
204 outl(command_que_value
, command_que_addr
);
206 /* Now poll for completion */
207 for (i
=0;i
<imax
;i
++) {
209 status_reg_value
= inl(status_reg_addr
);
210 if (tw_check_bits(status_reg_value
)) {
211 printk(KERN_WARNING
"3w-xxxx: tw_aen_drain_queue(): Unexpected bits.\n");
214 if ((status_reg_value
& TW_STATUS_RESPONSE_QUEUE_EMPTY
) == 0) {
215 response_queue
.value
= inl(response_que_addr
);
216 request_id
= (unsigned char)response_queue
.u
.response_id
;
218 if (request_id
!= 0) {
219 /* Unexpected request id */
220 printk(KERN_WARNING
"3w-xxxx: tw_aen_drain_queue(): Unexpected request id.\n");
224 if (command_packet
->status
!= 0) {
225 if (command_packet
->flags
!= TW_AEN_TABLE_UNDEFINED
) {
227 printk(KERN_WARNING
"3w-xxxx: tw_aen_drain_queue(): Bad response, flags = 0x%x.\n", command_packet
->flags
);
230 /* We know this is a 3w-1x00, and doesn't support aen's */
235 /* Now check the aen */
236 aen
= *(unsigned short *)(param
->data
);
237 aen_code
= (aen
& 0x0ff);
240 case TW_AEN_QUEUE_EMPTY
:
241 dprintk(KERN_NOTICE
"3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_QUEUE_EMPTY.\n");
242 if (first_reset
!= 1) {
248 case TW_AEN_SOFT_RESET
:
249 dprintk(KERN_NOTICE
"3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_SOFT_RESET.\n");
250 if (first_reset
== 0) {
256 case TW_AEN_DEGRADED_MIRROR
:
257 dprintk(KERN_NOTICE
"3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_DEGRADED_MIRROR.\n");
260 case TW_AEN_CONTROLLER_ERROR
:
261 dprintk(KERN_NOTICE
"3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_CONTROLLER_ERROR.\n");
264 case TW_AEN_REBUILD_FAIL
:
265 dprintk(KERN_NOTICE
"3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_REBUILD_FAIL.\n");
268 case TW_AEN_REBUILD_DONE
:
269 dprintk(KERN_NOTICE
"3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_REBUILD_DONE.\n");
272 case TW_AEN_QUEUE_FULL
:
273 dprintk(KERN_NOTICE
"3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_QUEUE_FULL.\n");
277 dprintk(KERN_WARNING
"3w-xxxx: tw_aen_drain_queue(): Unknown AEN code 0x%x.\n", aen_code
);
281 /* Now put the aen on the aen_queue */
283 tw_dev
->aen_queue
[tw_dev
->aen_tail
] = aen_code
;
284 if (tw_dev
->aen_tail
== TW_Q_LENGTH
- 1) {
285 tw_dev
->aen_tail
= TW_Q_START
;
287 tw_dev
->aen_tail
= tw_dev
->aen_tail
+ 1;
289 if (tw_dev
->aen_head
== tw_dev
->aen_tail
) {
290 if (tw_dev
->aen_head
== TW_Q_LENGTH
- 1) {
291 tw_dev
->aen_head
= TW_Q_START
;
293 tw_dev
->aen_head
= tw_dev
->aen_head
+ 1;
302 printk(KERN_WARNING
"3w-xxxx: tw_aen_drain_queue(): Response never received.\n");
306 } while ((tries
< TW_MAX_AEN_TRIES
) && (finished
== 0));
308 if (tries
>=TW_MAX_AEN_TRIES
) {
309 printk(KERN_WARNING
"3w-xxxx: tw_aen_drain_queue(): Aen queue error.\n");
314 } /* End tw_aen_drain_queue() */
316 /* This function will read the aen queue from the isr */
317 int tw_aen_read_queue(TW_Device_Extension
*tw_dev
, int request_id
)
319 TW_Command
*command_packet
;
321 u32 command_que_value
= 0, command_que_addr
;
322 u32 status_reg_value
= 0, status_reg_addr
;
325 dprintk(KERN_NOTICE
"3w-xxxx: tw_aen_read_queue()\n");
326 command_que_addr
= tw_dev
->registers
.command_que_addr
;
327 status_reg_addr
= tw_dev
->registers
.status_reg_addr
;
329 status_reg_value
= inl(status_reg_addr
);
330 if (tw_check_bits(status_reg_value
)) {
331 printk(KERN_WARNING
"3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n");
334 if (tw_dev
->command_packet_virtual_address
[request_id
] == NULL
) {
335 printk(KERN_WARNING
"3w-xxxx: tw_aen_read_queue(): Bad command packet virtual address.\n");
338 command_packet
= (TW_Command
*)tw_dev
->command_packet_virtual_address
[request_id
];
339 memset(command_packet
, 0, sizeof(TW_Sector
));
340 command_packet
->byte0
.opcode
= TW_OP_GET_PARAM
;
341 command_packet
->byte0
.sgl_offset
= 2;
342 command_packet
->size
= 4;
343 command_packet
->request_id
= request_id
;
344 command_packet
->byte3
.unit
= 0;
345 command_packet
->byte3
.host_id
= 0;
346 command_packet
->status
= 0;
347 command_packet
->flags
= 0;
348 command_packet
->byte6
.parameter_count
= 1;
349 command_que_value
= tw_dev
->command_packet_physical_address
[request_id
];
350 if (command_que_value
== 0) {
351 printk(KERN_WARNING
"3w-xxxx: tw_aen_read_queue(): Bad command packet physical address.\n");
354 /* Now setup the param */
355 if (tw_dev
->alignment_virtual_address
[request_id
] == NULL
) {
356 printk(KERN_WARNING
"3w-xxxx: tw_aen_read_queue(): Bad alignment virtual address.\n");
359 param
= (TW_Param
*)tw_dev
->alignment_virtual_address
[request_id
];
360 memset(param
, 0, sizeof(TW_Sector
));
361 param
->table_id
= 0x401; /* AEN table */
362 param
->parameter_id
= 2; /* Unit code */
363 param
->parameter_size_bytes
= 2;
364 param_value
= tw_dev
->alignment_physical_address
[request_id
];
365 if (param_value
== 0) {
366 printk(KERN_WARNING
"3w-xxxx: tw_aen_read_queue(): Bad alignment physical address.\n");
369 command_packet
->byte8
.param
.sgl
[0].address
= param_value
;
370 command_packet
->byte8
.param
.sgl
[0].length
= sizeof(TW_Sector
);
372 /* Now post the command packet */
373 if ((status_reg_value
& TW_STATUS_COMMAND_QUEUE_FULL
) == 0) {
374 dprintk(KERN_WARNING
"3w-xxxx: tw_aen_read_queue(): Post succeeded.\n");
375 tw_dev
->srb
[request_id
] = 0; /* Flag internal command */
376 tw_dev
->state
[request_id
] = TW_S_POSTED
;
377 outl(command_que_value
, command_que_addr
);
379 printk(KERN_WARNING
"3w-xxxx: tw_aen_read_queue(): Post failed, will retry.\n");
384 } /* End tw_aen_read_queue() */
386 /* This function will allocate memory and check if it is 16 d-word aligned */
387 int tw_allocate_memory(TW_Device_Extension
*tw_dev
, int request_id
, int size
, int which
)
391 dprintk(KERN_NOTICE
"3w-xxxx: tw_allocate_memory()\n");
394 /* Allocate command packet memory */
395 virt_addr
= kmalloc(size
, GFP_ATOMIC
);
396 if (virt_addr
== NULL
) {
397 printk(KERN_WARNING
"3w-xxxx: tw_allocate_memory(): kmalloc() failed.\n");
400 if ((u32
)virt_addr
% TW_ALIGNMENT
) {
401 printk(KERN_WARNING
"3w-xxxx: tw_allocate_memory(): Found unaligned address.\n");
404 tw_dev
->command_packet_virtual_address
[request_id
] = virt_addr
;
405 tw_dev
->command_packet_physical_address
[request_id
] =
406 virt_to_bus(virt_addr
);
408 /* Allocate generic buffer */
409 virt_addr
= kmalloc(size
, GFP_ATOMIC
);
410 if (virt_addr
== NULL
) {
411 printk(KERN_WARNING
"3w-xxxx: tw_allocate_memory(): kmalloc() failed.\n");
414 if ((u32
)virt_addr
% TW_ALIGNMENT
) {
415 printk(KERN_WARNING
"3w-xxxx: tw_allocate_memory(): Found unaligned address.\n");
418 tw_dev
->alignment_virtual_address
[request_id
] = virt_addr
;
419 tw_dev
->alignment_physical_address
[request_id
] = virt_to_bus(virt_addr
);
422 } /* End tw_allocate_memory() */
424 /* This function will check the status register for unexpected bits */
425 int tw_check_bits(u32 status_reg_value
)
427 if ((status_reg_value
& TW_STATUS_EXPECTED_BITS
) != TW_STATUS_EXPECTED_BITS
) {
428 printk(KERN_WARNING
"3w-xxxx: tw_check_bits(): No expected bits (0x%x).\n", status_reg_value
);
431 if ((status_reg_value
& TW_STATUS_UNEXPECTED_BITS
) != 0) {
432 printk(KERN_WARNING
"3w-xxxx: tw_check_bits(): Found unexpected bits (0x%x).\n", status_reg_value
);
437 } /* End tw_check_bits() */
439 /* This function will report controller error status */
440 int tw_check_errors(TW_Device_Extension
*tw_dev
)
442 u32 status_reg_addr
, status_reg_value
;
444 status_reg_addr
= tw_dev
->registers
.status_reg_addr
;
445 status_reg_value
= inl(status_reg_addr
);
447 if (TW_STATUS_ERRORS(status_reg_value
) || tw_check_bits(status_reg_value
))
451 } /* End tw_check_errors() */
453 /* This function will clear the attention interrupt */
454 void tw_clear_attention_interrupt(TW_Device_Extension
*tw_dev
)
456 u32 control_reg_addr
, control_reg_value
;
458 control_reg_addr
= tw_dev
->registers
.control_reg_addr
;
459 control_reg_value
= TW_CONTROL_CLEAR_ATTENTION_INTERRUPT
;
460 outl(control_reg_value
, control_reg_addr
);
461 } /* End tw_clear_attention_interrupt() */
463 /* This function will clear the host interrupt */
464 void tw_clear_host_interrupt(TW_Device_Extension
*tw_dev
)
466 u32 control_reg_addr
, control_reg_value
;
468 control_reg_addr
= tw_dev
->registers
.control_reg_addr
;
469 control_reg_value
= TW_CONTROL_CLEAR_HOST_INTERRUPT
;
470 outl(control_reg_value
, control_reg_addr
);
471 } /* End tw_clear_host_interrupt() */
473 /* This function is called by tw_scsi_proc_info */
474 static int tw_copy_info(TW_Info
*info
, char *fmt
, ...)
481 len
= vsprintf(buf
, fmt
, args
);
483 tw_copy_mem_info(info
, buf
, len
);
485 } /* End tw_copy_info() */
487 /* This function is called by tw_scsi_proc_info */
488 static void tw_copy_mem_info(TW_Info
*info
, char *data
, int len
)
490 if (info
->position
+ len
> info
->length
)
491 len
= info
->length
- info
->position
;
493 if (info
->position
+ len
< info
->offset
) {
494 info
->position
+= len
;
497 if (info
->position
< info
->offset
) {
498 data
+= (info
->offset
- info
->position
);
499 len
-= (info
->offset
- info
->position
);
502 memcpy(info
->buffer
+ info
->position
, data
, len
);
503 info
->position
+= len
;
505 } /* End tw_copy_mem_info() */
507 /* This function will disable interrupts on the controller */
508 void tw_disable_interrupts(TW_Device_Extension
*tw_dev
)
510 u32 control_reg_value
, control_reg_addr
;
512 control_reg_addr
= tw_dev
->registers
.control_reg_addr
;
513 control_reg_value
= TW_CONTROL_DISABLE_INTERRUPTS
;
514 outl(control_reg_value
, control_reg_addr
);
515 } /* End tw_disable_interrupts() */
517 /* This function will empty the response que */
518 int tw_empty_response_que(TW_Device_Extension
*tw_dev
)
520 u32 status_reg_addr
, status_reg_value
;
521 u32 response_que_addr
, response_que_value
;
523 status_reg_addr
= tw_dev
->registers
.status_reg_addr
;
524 response_que_addr
= tw_dev
->registers
.response_que_addr
;
526 status_reg_value
= inl(status_reg_addr
);
528 if (tw_check_bits(status_reg_value
)) {
529 printk(KERN_WARNING
"3w-xxxx: tw_empty_response_queue(): Unexpected bits 1.\n");
533 while ((status_reg_value
& TW_STATUS_RESPONSE_QUEUE_EMPTY
) == 0) {
534 response_que_value
= inl(response_que_addr
);
535 status_reg_value
= inl(status_reg_addr
);
536 if (tw_check_bits(status_reg_value
)) {
537 printk(KERN_WARNING
"3w-xxxx: tw_empty_response_queue(): Unexpected bits 2.\n");
542 } /* End tw_empty_response_que() */
544 /* This function will enable interrupts on the controller */
545 void tw_enable_interrupts(TW_Device_Extension
*tw_dev
)
547 u32 control_reg_value
, control_reg_addr
;
549 control_reg_addr
= tw_dev
->registers
.control_reg_addr
;
550 control_reg_value
= (TW_CONTROL_CLEAR_ATTENTION_INTERRUPT
|
551 TW_CONTROL_UNMASK_RESPONSE_INTERRUPT
|
552 TW_CONTROL_ENABLE_INTERRUPTS
);
553 outl(control_reg_value
, control_reg_addr
);
554 } /* End tw_enable_interrupts() */
556 /* This function will find and initialize all cards */
557 int tw_findcards(Scsi_Host_Template
*tw_host
)
559 int numcards
= 0, tries
= 0, error
= 0;
560 struct Scsi_Host
*host
;
561 TW_Device_Extension
*tw_dev
;
562 TW_Device_Extension
*tw_dev2
;
563 struct pci_dev
*tw_pci_dev
= NULL
;
564 u32 status_reg_value
;
566 dprintk(KERN_NOTICE
"3w-xxxx: tw_findcards()\n");
567 while ((tw_pci_dev
= pci_find_device(TW_VENDOR_ID
, TW_DEVICE_ID
, tw_pci_dev
))) {
568 /* Prepare temporary device extension */
569 tw_dev
=(TW_Device_Extension
*)kmalloc(sizeof(TW_Device_Extension
), GFP_ATOMIC
);
570 if (tw_dev
== NULL
) {
571 printk(KERN_WARNING
"3w-xxxx: tw_findcards(): kmalloc() failed for card %d.\n", numcards
);
574 memset(tw_dev
, 0, sizeof(TW_Device_Extension
));
576 error
= tw_initialize_device_extension(tw_dev
);
578 printk(KERN_WARNING
"3w-xxxx: tw_findcards(): Couldn't initialize device extension for card %d.\n", numcards
);
579 tw_free_device_extension(tw_dev
);
584 /* Calculate the cards register addresses */
585 tw_dev
->registers
.base_addr
= tw_pci_dev
->resource
[0].start
;
586 tw_dev
->registers
.control_reg_addr
= (tw_pci_dev
->resource
[0].start
& ~15);
587 tw_dev
->registers
.status_reg_addr
= ((tw_pci_dev
->resource
[0].start
& ~15) + 0x4);
588 tw_dev
->registers
.command_que_addr
= ((tw_pci_dev
->resource
[0].start
& ~15) + 0x8);
589 tw_dev
->registers
.response_que_addr
= ((tw_pci_dev
->resource
[0].start
& ~15) + 0xC);
590 /* Save pci_dev struct to device extension */
591 tw_dev
->tw_pci_dev
= tw_pci_dev
;
593 /* Poll status register for 60 secs for 'Controller Ready' flag */
594 if (tw_poll_status(tw_dev
, TW_STATUS_MICROCONTROLLER_READY
, 60)) {
595 printk(KERN_WARNING
"3w-xxxx: tw_findcards(): Microcontroller not ready for card %d.\n", numcards
);
596 tw_free_device_extension(tw_dev
);
601 /* Disable interrupts on the card */
602 tw_disable_interrupts(tw_dev
);
604 while (tries
< TW_MAX_RESET_TRIES
) {
606 tw_soft_reset(tw_dev
);
608 error
= tw_aen_drain_queue(tw_dev
);
610 printk(KERN_WARNING
"3w-xxxx: tw_findcards(): No attention interrupt for card %d.\n", numcards
);
615 /* Check for controller errors */
616 if (tw_check_errors(tw_dev
)) {
617 printk(KERN_WARNING
"3w-xxxx: tw_findcards(): Controller errors found, soft resetting card %d.\n", numcards
);
622 /* Empty the response queue */
623 error
= tw_empty_response_que(tw_dev
);
625 printk(KERN_WARNING
"3w-xxxx: tw_findcards(): Couldn't empty response queue for card %d.\n", numcards
);
630 /* Now the controller is in a good state */
634 if (tries
>= TW_MAX_RESET_TRIES
) {
635 printk(KERN_WARNING
"3w-xxxx: tw_findcards(): Controller error or no attention interrupt: giving up for card %d.\n", numcards
);
636 tw_free_device_extension(tw_dev
);
641 /* Make sure that io region isn't already taken */
642 if (check_region((tw_dev
->tw_pci_dev
->resource
[0].start
), TW_IO_ADDRESS_RANGE
)) {
643 printk(KERN_WARNING
"3w-xxxx: tw_findcards(): Couldn't get io range 0x%lx-0x%lx for card %d.\n",
644 (tw_dev
->tw_pci_dev
->resource
[0].start
),
645 (tw_dev
->tw_pci_dev
->resource
[0].start
) +
646 TW_IO_ADDRESS_RANGE
, numcards
);
647 tw_free_device_extension(tw_dev
);
652 /* Reserve the io address space */
653 request_region((tw_dev
->tw_pci_dev
->resource
[0].start
), TW_IO_ADDRESS_RANGE
, TW_DEVICE_NAME
);
654 error
= tw_initialize_units(tw_dev
);
656 printk(KERN_WARNING
"3w-xxxx: tw_findcards(): Couldn't initialize units for card %d.\n", numcards
);
657 release_region((tw_dev
->tw_pci_dev
->resource
[0].start
), TW_IO_ADDRESS_RANGE
);
658 tw_free_device_extension(tw_dev
);
663 error
= tw_initconnection(tw_dev
);
665 printk(KERN_WARNING
"3w-xxxx: tw_findcards(): Couldn't initconnection for card %d.\n", numcards
);
666 release_region((tw_dev
->tw_pci_dev
->resource
[0].start
), TW_IO_ADDRESS_RANGE
);
667 tw_free_device_extension(tw_dev
);
672 /* Calculate max cmds per lun */
673 if (tw_dev
->num_units
> 0)
674 tw_host
->cmd_per_lun
= (TW_Q_LENGTH
-2)/tw_dev
->num_units
;
676 /* Register the card with the kernel SCSI layer */
677 host
= scsi_register(tw_host
, sizeof(TW_Device_Extension
));
679 /* FIXME - check for NULL */
681 status_reg_value
= inl(tw_dev
->registers
.status_reg_addr
);
683 dprintk(KERN_NOTICE
"scsi%d : Found a 3ware Storage Controller at 0x%x, IRQ: %d P-chip: %d.%d\n", host
->host_no
,
684 (u32
)(tw_pci_dev
->resource
[0].start
), tw_pci_dev
->irq
,
685 (status_reg_value
& TW_STATUS_MAJOR_VERSION_MASK
) >> 28,
686 (status_reg_value
& TW_STATUS_MINOR_VERSION_MASK
) >> 24);
688 if (host
->hostdata
) {
689 tw_dev2
= (TW_Device_Extension
*)host
->hostdata
;
690 memcpy(tw_dev2
, tw_dev
, sizeof(TW_Device_Extension
));
691 tw_device_extension_list
[tw_device_extension_count
] = tw_dev2
;
693 tw_device_extension_count
= numcards
;
694 tw_dev2
->host
= host
;
696 printk(KERN_WARNING
"3w-xxxx: tw_findcards(): Bad scsi host data for card %d.\n", numcards
-1);
697 scsi_unregister(host
);
698 release_region((tw_dev
->tw_pci_dev
->resource
[0].start
), TW_IO_ADDRESS_RANGE
);
699 tw_free_device_extension(tw_dev
);
704 /* Re-enable interrupts on the card */
705 tw_enable_interrupts(tw_dev2
);
707 /* Now setup the interrupt handler */
708 error
= tw_setup_irq(tw_dev2
);
710 printk(KERN_WARNING
"3w-xxxx: tw_findcards(): Error requesting irq for card %d.\n", numcards
-1);
711 scsi_unregister(host
);
712 release_region((tw_dev
->tw_pci_dev
->resource
[0].start
), TW_IO_ADDRESS_RANGE
);
714 tw_free_device_extension(tw_dev
);
720 /* Free the temporary device extension */
726 printk(KERN_WARNING
"3w-xxxx: tw_findcards(): No cards found.\n");
729 } /* End tw_findcards() */
731 /* This function will free up device extension resources */
732 void tw_free_device_extension(TW_Device_Extension
*tw_dev
)
737 dprintk(KERN_NOTICE
"3w-xxxx: tw_free_device_extension()\n");
738 /* Free command packet and generic buffer memory */
739 for (i
=0;i
<imax
;i
++) {
740 if (tw_dev
->command_packet_virtual_address
[i
])
741 kfree(tw_dev
->command_packet_virtual_address
[i
]);
743 if (tw_dev
->alignment_virtual_address
[i
])
744 kfree(tw_dev
->alignment_virtual_address
[i
]);
746 } /* End tw_free_device_extension() */
748 /* This function will send an initconnection command to controller */
749 int tw_initconnection(TW_Device_Extension
*tw_dev
)
751 u32 command_que_addr
, command_que_value
;
752 u32 status_reg_addr
, status_reg_value
;
753 u32 response_que_addr
;
754 TW_Command
*command_packet
;
755 TW_Response_Queue response_queue
;
760 dprintk(KERN_NOTICE
"3w-xxxx: tw_initconnection()\n");
761 command_que_addr
= tw_dev
->registers
.command_que_addr
;
762 status_reg_addr
= tw_dev
->registers
.status_reg_addr
;
763 response_que_addr
= tw_dev
->registers
.response_que_addr
;
765 /* Initialize InitConnection command packet */
766 if (tw_dev
->command_packet_virtual_address
[request_id
] == NULL
) {
767 printk(KERN_WARNING
"3w-xxxx: tw_initconnection(): Bad command packet virtual address.\n");
771 command_packet
= (TW_Command
*)tw_dev
->command_packet_virtual_address
[request_id
];
772 memset(command_packet
, 0, sizeof(TW_Sector
));
773 command_packet
->byte0
.opcode
= TW_OP_INIT_CONNECTION
;
774 command_packet
->byte0
.sgl_offset
= 0x0;
775 command_packet
->size
= TW_INIT_COMMAND_PACKET_SIZE
;
776 command_packet
->request_id
= request_id
;
777 command_packet
->byte3
.unit
= 0x0;
778 command_packet
->byte3
.host_id
= 0x0;
779 command_packet
->status
= 0x0;
780 command_packet
->flags
= 0x0;
781 command_packet
->byte6
.message_credits
= TW_INIT_MESSAGE_CREDITS
;
782 command_packet
->byte8
.init_connection
.response_queue_pointer
= 0x0;
783 command_que_value
= tw_dev
->command_packet_physical_address
[request_id
];
785 if (command_que_value
== 0) {
786 printk(KERN_WARNING
"3w-xxxx: tw_initconnection(): Bad command packet physical address.\n");
790 /* Send command packet to the board */
791 outl(command_que_value
, command_que_addr
);
793 /* Poll for completion */
794 imax
= TW_POLL_MAX_RETRIES
;
795 for (i
=0;i
<imax
;i
++) {
797 status_reg_value
= inl(status_reg_addr
);
798 if (tw_check_bits(status_reg_value
)) {
799 printk(KERN_WARNING
"3w-xxxx: tw_initconnection(): Unexpected bits.\n");
802 if ((status_reg_value
& TW_STATUS_RESPONSE_QUEUE_EMPTY
) == 0) {
803 response_queue
.value
= inl(response_que_addr
);
804 request_id
= (unsigned char)response_queue
.u
.response_id
;
805 if (request_id
!= 0) {
806 /* unexpected request id */
807 printk(KERN_WARNING
"3w-xxxx: tw_initconnection(): Unexpected request id.\n");
810 if (command_packet
->status
!= 0) {
812 printk(KERN_WARNING
"3w-xxxx: tw_initconnection(): Bad response, flags = 0x%x.\n", command_packet
->flags
);
815 break; /* Response was okay, so we exit */
819 } /* End tw_initconnection() */
821 /* This function will initialize the fields of a device extension */
822 int tw_initialize_device_extension(TW_Device_Extension
*tw_dev
)
826 dprintk(KERN_NOTICE
"3w-xxxx: tw_initialize_device_extension()\n");
829 for (i
=0; i
<imax
; i
++) {
830 /* Initialize command packet buffers */
831 tw_allocate_memory(tw_dev
, i
, sizeof(TW_Sector
), 0);
832 if (tw_dev
->command_packet_virtual_address
[i
] == NULL
) {
833 printk(KERN_WARNING
"3w-xxxx: tw_initialize_device_extension(): Bad command packet virtual address.\n");
836 memset(tw_dev
->command_packet_virtual_address
[i
], 0, sizeof(TW_Sector
));
838 /* Initialize generic buffer */
839 tw_allocate_memory(tw_dev
, i
, sizeof(TW_Sector
), 1);
840 if (tw_dev
->alignment_virtual_address
[i
] == NULL
) {
841 printk(KERN_WARNING
"3w-xxxx: tw_initialize_device_extension(): Bad alignment virtual address.\n");
844 memset(tw_dev
->alignment_virtual_address
[i
], 0, sizeof(TW_Sector
));
846 tw_dev
->free_queue
[i
] = i
;
847 tw_dev
->state
[i
] = TW_S_INITIAL
;
848 tw_dev
->ioctl_size
[i
] = 0;
849 tw_dev
->aen_queue
[i
] = 0;
852 for (i
=0;i
<TW_MAX_UNITS
;i
++)
853 tw_dev
->is_unit_present
[i
] = 0;
855 tw_dev
->num_units
= 0;
856 tw_dev
->num_aborts
= 0;
857 tw_dev
->num_resets
= 0;
858 tw_dev
->free_head
= TW_Q_START
;
859 tw_dev
->free_tail
= TW_Q_LENGTH
- 1;
860 tw_dev
->posted_request_count
= 0;
861 tw_dev
->max_posted_request_count
= 0;
862 tw_dev
->max_sgl_entries
= 0;
863 tw_dev
->sgl_entries
= 0;
865 tw_dev
->pending_head
= TW_Q_START
;
866 tw_dev
->pending_tail
= TW_Q_START
;
867 tw_dev
->aen_head
= 0;
868 tw_dev
->aen_tail
= 0;
869 tw_dev
->sector_count
= 0;
870 tw_dev
->max_sector_count
= 0;
871 spin_lock_init(&tw_dev
->tw_lock
);
874 } /* End tw_initialize_device_extension() */
876 /* This function will get unit info from the controller */
877 int tw_initialize_units(TW_Device_Extension
*tw_dev
)
880 unsigned char request_id
= 0;
881 TW_Command
*command_packet
;
883 int i
, imax
, num_units
= 0;
884 u32 status_reg_addr
, status_reg_value
;
885 u32 command_que_addr
, command_que_value
;
886 u32 response_que_addr
;
887 TW_Response_Queue response_queue
;
889 unsigned char *is_unit_present
;
891 dprintk(KERN_NOTICE
"3w-xxxx: tw_initialize_units()\n");
893 status_reg_addr
= tw_dev
->registers
.status_reg_addr
;
894 command_que_addr
= tw_dev
->registers
.command_que_addr
;
895 response_que_addr
= tw_dev
->registers
.response_que_addr
;
897 /* Setup the command packet */
898 command_packet
= (TW_Command
*)tw_dev
->command_packet_virtual_address
[request_id
];
899 if (command_packet
== NULL
) {
900 printk(KERN_WARNING
"3w-xxxx: tw_initialize_units(): Bad command packet virtual address.\n");
903 memset(command_packet
, 0, sizeof(TW_Sector
));
904 command_packet
->byte0
.opcode
= TW_OP_GET_PARAM
;
905 command_packet
->byte0
.sgl_offset
= 2;
906 command_packet
->size
= 4;
907 command_packet
->request_id
= request_id
;
908 command_packet
->byte3
.unit
= 0;
909 command_packet
->byte3
.host_id
= 0;
910 command_packet
->status
= 0;
911 command_packet
->flags
= 0;
912 command_packet
->byte6
.block_count
= 1;
914 /* Now setup the param */
915 if (tw_dev
->alignment_virtual_address
[request_id
] == NULL
) {
916 printk(KERN_WARNING
"3w-xxxx: tw_initialize_units(): Bad alignment virtual address.\n");
919 param
= (TW_Param
*)tw_dev
->alignment_virtual_address
[request_id
];
920 memset(param
, 0, sizeof(TW_Sector
));
921 param
->table_id
= 3; /* unit summary table */
922 param
->parameter_id
= 3; /* unitstatus parameter */
923 param
->parameter_size_bytes
= TW_MAX_UNITS
;
924 param_value
= tw_dev
->alignment_physical_address
[request_id
];
925 if (param_value
== 0) {
926 printk(KERN_WARNING
"3w-xxxx: tw_initialize_units(): Bad alignment physical address.\n");
930 command_packet
->byte8
.param
.sgl
[0].address
= param_value
;
931 command_packet
->byte8
.param
.sgl
[0].length
= sizeof(TW_Sector
);
933 /* Post the command packet to the board */
934 command_que_value
= tw_dev
->command_packet_physical_address
[request_id
];
935 if (command_que_value
== 0) {
936 printk(KERN_WARNING
"3w-xxxx: tw_initialize_units(): Bad command packet physical address.\n");
939 outl(command_que_value
, command_que_addr
);
941 /* Poll for completion */
942 imax
= TW_POLL_MAX_RETRIES
;
943 for(i
=0; i
<imax
; i
++) {
945 status_reg_value
= inl(status_reg_addr
);
946 if (tw_check_bits(status_reg_value
)) {
947 printk(KERN_WARNING
"3w-xxxx: tw_initialize_units(): Unexpected bits.\n");
950 if ((status_reg_value
& TW_STATUS_RESPONSE_QUEUE_EMPTY
) == 0) {
951 response_queue
.value
= inl(response_que_addr
);
952 request_id
= (unsigned char)response_queue
.u
.response_id
;
953 if (request_id
!= 0) {
954 /* unexpected request id */
955 printk(KERN_WARNING
"3w-xxxx: tw_initialize_units(): Unexpected request id.\n");
958 if (command_packet
->status
!= 0) {
960 printk(KERN_WARNING
"3w-xxxx: tw_initialize_units(): Bad response, flags = 0x%x.\n", command_packet
->flags
);
968 /* response never received */
969 printk(KERN_WARNING
"3w-xxxx: tw_initialize_units(): No response.\n");
973 param
= (TW_Param
*)tw_dev
->alignment_virtual_address
[request_id
];
974 is_unit_present
= (unsigned char *)&(param
->data
[0]);
976 /* Show all units present */
978 for(i
=0; i
<imax
; i
++) {
979 if (is_unit_present
[i
] == 0) {
980 tw_dev
->is_unit_present
[i
] = FALSE
;
982 dprintk(KERN_NOTICE
"3w-xxxx: tw_initialize_units(): Unit %d found.\n", i
);
983 tw_dev
->is_unit_present
[i
] = TRUE
;
987 tw_dev
->num_units
= num_units
;
989 if (num_units
== 0) {
990 printk(KERN_NOTICE
"3w-xxxx: tw_initialize_units(): No units found.\n");
995 } /* End tw_initialize_units() */
997 /* This function is the interrupt service routine */
998 static void tw_interrupt(int irq
, void *dev_instance
, struct pt_regs
*regs
)
1001 u32 status_reg_addr
, status_reg_value
;
1002 u32 response_que_addr
;
1003 TW_Device_Extension
*tw_dev
= (TW_Device_Extension
*)dev_instance
;
1004 TW_Response_Queue response_que
;
1006 int do_response_interrupt
=0;
1007 int do_attention_interrupt
=0;
1008 int do_host_interrupt
=0;
1009 int do_command_interrupt
=0;
1012 TW_Command
*command_packet
;
1013 if (test_and_set_bit(TW_IN_INTR
, &tw_dev
->flags
))
1015 spin_lock_irqsave(&io_request_lock
, flags
);
1017 if (tw_dev
->tw_pci_dev
->irq
== irq
) {
1018 spin_lock_irqsave(&tw_dev
->tw_lock
, flags2
);
1019 dprintk(KERN_NOTICE
"3w-xxxx: tw_interrupt()\n");
1021 /* Read the registers */
1022 status_reg_addr
= tw_dev
->registers
.status_reg_addr
;
1023 response_que_addr
= tw_dev
->registers
.response_que_addr
;
1024 status_reg_value
= inl(status_reg_addr
);
1026 /* Check which interrupt */
1027 if (status_reg_value
& TW_STATUS_HOST_INTERRUPT
)
1028 do_host_interrupt
=1;
1029 if (status_reg_value
& TW_STATUS_ATTENTION_INTERRUPT
)
1030 do_attention_interrupt
=1;
1031 if (status_reg_value
& TW_STATUS_COMMAND_INTERRUPT
)
1032 do_command_interrupt
=1;
1033 if (status_reg_value
& TW_STATUS_RESPONSE_INTERRUPT
)
1034 do_response_interrupt
=1;
1036 /* Handle host interrupt */
1037 if (do_host_interrupt
) {
1038 dprintk(KERN_NOTICE
"3w-xxxx: tw_interrupt(): Received host interrupt.\n");
1039 tw_clear_host_interrupt(tw_dev
);
1042 /* Handle attention interrupt */
1043 if (do_attention_interrupt
) {
1044 dprintk(KERN_NOTICE
"3w-xxxx: tw_interrupt(): Received attention interrupt.\n");
1045 tw_state_request_start(tw_dev
, &request_id
);
1046 error
= tw_aen_read_queue(tw_dev
, request_id
);
1048 printk(KERN_WARNING
"3w-xxxx: tw_interrupt(): Error reading aen queue.\n");
1049 tw_dev
->state
[request_id
] = TW_S_COMPLETED
;
1050 tw_state_request_finish(tw_dev
, request_id
);
1052 dprintk(KERN_WARNING
"3w-xxxx: tw_interrupt(): Clearing attention interrupt.\n");
1053 tw_clear_attention_interrupt(tw_dev
);
1057 /* Handle command interrupt */
1058 if (do_command_interrupt
) {
1059 /* Drain as many pending commands as we can */
1060 while (tw_dev
->pending_request_count
> 0) {
1061 request_id
= tw_dev
->pending_queue
[tw_dev
->pending_head
];
1062 if (tw_dev
->state
[request_id
] != TW_S_PENDING
) {
1063 printk(KERN_WARNING
"3w-xxxx: tw_interrupt(): Found request id that wasn't pending.\n");
1066 if (tw_post_command_packet(tw_dev
, request_id
)==0) {
1067 if (tw_dev
->pending_head
== TW_Q_LENGTH
-1) {
1068 tw_dev
->pending_head
= TW_Q_START
;
1070 tw_dev
->pending_head
= tw_dev
->pending_head
+ 1;
1072 tw_dev
->pending_request_count
--;
1077 /* If there are no more pending requests, we mask command interrupt */
1078 if (tw_dev
->pending_request_count
== 0)
1079 tw_mask_command_interrupt(tw_dev
);
1082 /* Handle response interrupt */
1083 if (do_response_interrupt
) {
1084 /* Drain the response queue from the board */
1085 while ((status_reg_value
& TW_STATUS_RESPONSE_QUEUE_EMPTY
) == 0) {
1086 response_que
.value
= inl(response_que_addr
);
1087 request_id
= response_que
.u
.response_id
;
1088 command_packet
= (TW_Command
*)tw_dev
->command_packet_virtual_address
[request_id
];
1089 if (command_packet
->status
!= 0) {
1090 printk(KERN_WARNING
"3w-xxxx: tw_interrupt(): Bad response, flags = 0x%x.\n", command_packet
->flags
);
1092 if (tw_dev
->state
[request_id
] != TW_S_POSTED
) {
1093 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
);
1096 dprintk(KERN_NOTICE
"3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id
);
1097 /* Check for internal command */
1098 if (tw_dev
->srb
[request_id
] == 0) {
1099 dprintk(KERN_WARNING
"3w-xxxx: tw_interrupt(): Found internally posted command.\n");
1100 error
= tw_aen_complete(tw_dev
, request_id
);
1102 printk(KERN_WARNING
"3w-xxxx: tw_interrupt(): Error completing aen.\n");
1104 status_reg_value
= inl(status_reg_addr
);
1105 if (tw_check_bits(status_reg_value
)) {
1106 printk(KERN_WARNING
"3w-xxxx: tw_interrupt(): Unexpected bits.\n");
1109 switch (tw_dev
->srb
[request_id
]->cmnd
[0]) {
1111 dprintk(KERN_NOTICE
"3w-xxxx: tw_interrupt(): caught READ_10\n");
1113 dprintk(KERN_NOTICE
"3w-xxxx: tw_interrupt(): caught READ_6\n");
1116 dprintk(KERN_NOTICE
"3w-xxxx: tw_interrupt(): caught WRITE_10\n");
1118 dprintk(KERN_NOTICE
"3w-xxxx: tw_interrupt(): caught WRITE_6\n");
1121 dprintk(KERN_NOTICE
"3w-xxxx: tw_interrupt(): caught INQUIRY\n");
1122 error
= tw_scsiop_inquiry_complete(tw_dev
, request_id
);
1125 dprintk(KERN_NOTICE
"3w-xxxx: tw_interrupt(): caught READ_CAPACITY\n");
1126 error
= tw_scsiop_read_capacity_complete(tw_dev
, request_id
);
1129 dprintk(KERN_NOTICE
"3w-xxxx: tw_interrupt(): caught TW_IOCTL\n");
1130 error
= tw_ioctl_complete(tw_dev
, request_id
);
1133 printk(KERN_WARNING
"3w-xxxx: tw_interrupt(): Unknown scsi opcode: 0x%x.\n", tw_dev
->srb
[request_id
]->cmnd
[0]);
1134 tw_dev
->srb
[request_id
]->result
= (DID_BAD_TARGET
<< 16);
1135 tw_dev
->srb
[request_id
]->scsi_done(tw_dev
->srb
[request_id
]);
1138 /* Tell scsi layer there was an error */
1139 printk(KERN_WARNING
"3w-xxxx: tw_interrupt(): Scsi Error.\n");
1140 tw_dev
->srb
[request_id
]->result
= (DID_ERROR
<< 16);
1142 /* Tell scsi layer command was a success */
1143 tw_dev
->srb
[request_id
]->result
= (DID_OK
<< 16);
1145 tw_dev
->state
[request_id
] = TW_S_COMPLETED
;
1146 tw_state_request_finish(tw_dev
, request_id
);
1147 tw_dev
->posted_request_count
--;
1148 tw_dev
->srb
[request_id
]->scsi_done(tw_dev
->srb
[request_id
]);
1149 status_reg_value
= inl(status_reg_addr
);
1150 if (tw_check_bits(status_reg_value
)) {
1151 printk(KERN_WARNING
"3w-xxxx: tw_interrupt(): Unexpected bits.\n");
1156 spin_unlock_irqrestore(&tw_dev
->tw_lock
, flags2
);
1158 spin_unlock_irqrestore(&io_request_lock
, flags
);
1159 clear_bit(TW_IN_INTR
, &tw_dev
->flags
);
1160 } /* End tw_interrupt() */
1162 /* This function handles ioctls from userspace to the driver */
1163 int tw_ioctl(TW_Device_Extension
*tw_dev
, int request_id
)
1165 unsigned char opcode
;
1168 TW_Command
*command_packet
;
1170 TW_Ioctl
*ioctl
= NULL
;
1173 ioctl
= (TW_Ioctl
*)tw_dev
->srb
[request_id
]->request_buffer
;
1174 if (ioctl
== NULL
) {
1175 printk(KERN_WARNING
"3w-xxxx: tw_ioctl(): Request buffer NULL.\n");
1176 tw_dev
->state
[request_id
] = TW_S_COMPLETED
;
1177 tw_state_request_finish(tw_dev
, request_id
);
1178 tw_dev
->srb
[request_id
]->result
= (DID_OK
<< 16);
1179 tw_dev
->srb
[request_id
]->scsi_done(tw_dev
->srb
[request_id
]);
1182 bufflen
= tw_dev
->srb
[request_id
]->request_bufflen
;
1184 /* Initialize command packet */
1185 command_packet
= (TW_Command
*)tw_dev
->command_packet_virtual_address
[request_id
];
1186 if (command_packet
== NULL
) {
1187 printk(KERN_WARNING
"3w-xxxx: twioctl(): Bad command packet virtual address.\n");
1188 tw_dev
->state
[request_id
] = TW_S_COMPLETED
;
1189 tw_state_request_finish(tw_dev
, request_id
);
1190 tw_dev
->srb
[request_id
]->result
= (DID_OK
<< 16);
1191 tw_dev
->srb
[request_id
]->scsi_done(tw_dev
->srb
[request_id
]);
1194 memset(command_packet
, 0, sizeof(TW_Sector
));
1196 /* Initialize param */
1197 if (tw_dev
->alignment_virtual_address
[request_id
] == NULL
) {
1198 printk(KERN_WARNING
"3w-xxxx: tw_ioctl(): Bad alignment virtual address.\n");
1199 tw_dev
->state
[request_id
] = TW_S_COMPLETED
;
1200 tw_state_request_finish(tw_dev
, request_id
);
1201 tw_dev
->srb
[request_id
]->result
= (DID_OK
<< 16);
1202 tw_dev
->srb
[request_id
]->scsi_done(tw_dev
->srb
[request_id
]);
1205 param
= (TW_Param
*)tw_dev
->alignment_virtual_address
[request_id
];
1206 memset(param
, 0, sizeof(TW_Sector
));
1208 dprintk(KERN_NOTICE
"opcode = %d table_id = %d parameter_id = %d parameter_size_bytes = %d\n", ioctl
->opcode
, ioctl
->table_id
, ioctl
->parameter_id
,, ioctl
->parameter_size_bytes
);
1209 opcode
= ioctl
->opcode
;
1213 dprintk(KERN_NOTICE
"3w-xxxx: tw_ioctl(): caught TW_OP_NOP.\n");
1214 command_packet
->byte0
.opcode
= TW_OP_NOP
;
1216 case TW_OP_GET_PARAM
:
1217 dprintk(KERN_NOTICE
"3w-xxxx: tw_ioctl(): caught TW_OP_GET_PARAM.\n");
1218 command_packet
->byte0
.opcode
= TW_OP_GET_PARAM
;
1219 param
->table_id
= ioctl
->table_id
;
1220 param
->parameter_id
= ioctl
->parameter_id
;
1221 param
->parameter_size_bytes
= ioctl
->parameter_size_bytes
;
1222 tw_dev
->ioctl_size
[request_id
] = ioctl
->parameter_size_bytes
;
1223 dprintk(KERN_NOTICE
"table_id = %d parameter_id = %d parameter_size_bytes %d\n", param
->table_id
, param
->parameter_id
, param
->parameter_size_bytes
);
1225 case TW_OP_SET_PARAM
:
1226 dprintk(KERN_NOTICE
"3w-xxxx: tw_ioctl(): caught TW_OP_SET_PARAM: table_id = %d, parameter_id = %d, parameter_size_bytes = %d.\n",
1227 ioctl
->table_id
, ioctl
->parameter_id
, ioctl
->parameter_size_bytes
);
1228 command_packet
->byte0
.opcode
= TW_OP_SET_PARAM
;
1229 param
->table_id
= ioctl
->table_id
;
1230 param
->parameter_id
= ioctl
->parameter_id
;
1231 param
->parameter_size_bytes
= ioctl
->parameter_size_bytes
;
1232 memcpy(param
->data
, ioctl
->data
, ioctl
->parameter_size_bytes
);
1234 case TW_OP_AEN_LISTEN
:
1235 dprintk(KERN_NOTICE
"3w-xxxx: tw_ioctl(): caught TW_OP_AEN_LISTEN.\n");
1236 if (tw_dev
->aen_head
== tw_dev
->aen_tail
) {
1237 /* aen queue empty */
1238 dprintk(KERN_NOTICE
"3w-xxxx: tw_ioctl(): Aen queue empty.\n");
1239 tw_aen_code
= TW_AEN_QUEUE_EMPTY
;
1240 memcpy(tw_dev
->srb
[request_id
]->request_buffer
, &tw_aen_code
, ioctl
->parameter_size_bytes
);
1242 /* Copy aen queue entry to request buffer */
1243 dprintk(KERN_NOTICE
"3w-xxxx: tw_ioctl(): Returning aen 0x%x\n", tw_dev
->aen_queue
[tw_dev
->aen_head
]);
1244 tw_aen_code
= tw_dev
->aen_queue
[tw_dev
->aen_head
];
1245 memcpy(tw_dev
->srb
[request_id
]->request_buffer
, &tw_aen_code
, ioctl
->parameter_size_bytes
);
1246 if (tw_dev
->aen_head
== TW_Q_LENGTH
- 1) {
1247 tw_dev
->aen_head
= TW_Q_START
;
1249 tw_dev
->aen_head
= tw_dev
->aen_head
+ 1;
1252 tw_dev
->state
[request_id
] = TW_S_COMPLETED
;
1253 tw_state_request_finish(tw_dev
, request_id
);
1254 tw_dev
->srb
[request_id
]->result
= (DID_OK
<< 16);
1255 tw_dev
->srb
[request_id
]->scsi_done(tw_dev
->srb
[request_id
]);
1258 printk(KERN_WARNING
"3w-xxxx: Unknown ioctl 0x%x.\n", opcode
);
1259 tw_dev
->state
[request_id
] = TW_S_COMPLETED
;
1260 tw_state_request_finish(tw_dev
, request_id
);
1261 tw_dev
->srb
[request_id
]->result
= (DID_OK
<< 16);
1262 tw_dev
->srb
[request_id
]->scsi_done(tw_dev
->srb
[request_id
]);
1266 param_value
= tw_dev
->alignment_physical_address
[request_id
];
1267 if (param_value
== 0) {
1268 printk(KERN_WARNING
"3w-xxxx: tw_ioctl(): Bad alignment physical address.\n");
1269 tw_dev
->state
[request_id
] = TW_S_COMPLETED
;
1270 tw_state_request_finish(tw_dev
, request_id
);
1271 tw_dev
->srb
[request_id
]->result
= (DID_OK
<< 16);
1272 tw_dev
->srb
[request_id
]->scsi_done(tw_dev
->srb
[request_id
]);
1275 command_packet
->byte8
.param
.sgl
[0].address
= param_value
;
1276 command_packet
->byte8
.param
.sgl
[0].length
= sizeof(TW_Sector
);
1278 command_packet
->byte0
.sgl_offset
= 2;
1279 command_packet
->size
= 4;
1280 command_packet
->request_id
= request_id
;
1281 command_packet
->byte3
.unit
= 0;
1282 command_packet
->byte3
.host_id
= 0;
1283 command_packet
->status
= 0;
1284 command_packet
->flags
= 0;
1285 command_packet
->byte6
.parameter_count
= 1;
1287 /* Now try to post the command to the board */
1288 tw_post_command_packet(tw_dev
, request_id
);
1291 } /* End tw_ioctl() */
1293 /* This function is called by the isr to complete ioctl requests */
1294 int tw_ioctl_complete(TW_Device_Extension
*tw_dev
, int request_id
)
1296 unsigned char *param_data
;
1297 unsigned char *buff
;
1300 dprintk(KERN_NOTICE
"3w-xxxx: tw_ioctl_complete()\n");
1301 buff
= tw_dev
->srb
[request_id
]->request_buffer
;
1303 printk(KERN_WARNING
"3w-xxxx: tw_ioctl_complete(): Request buffer NULL.\n");
1306 dprintk(KERN_NOTICE
"3w-xxxx: tw_ioctl_complete(): Request_bufflen = %d\n", tw_dev
->srb
[request_id
]->request_bufflen
);
1307 memset(buff
, 0, tw_dev
->srb
[request_id
]->request_bufflen
);
1308 param
= (TW_Param
*)tw_dev
->alignment_virtual_address
[request_id
];
1309 if (param
== NULL
) {
1310 printk(KERN_WARNING
"3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n");
1313 param_data
= &(param
->data
[0]);
1315 memcpy(buff
, param_data
, tw_dev
->ioctl_size
[request_id
]);
1318 } /* End tw_ioctl_complete() */
1320 /* This function will mask the command interrupt */
1321 void tw_mask_command_interrupt(TW_Device_Extension
*tw_dev
)
1323 u32 control_reg_addr
, control_reg_value
;
1325 control_reg_addr
= tw_dev
->registers
.control_reg_addr
;
1326 control_reg_value
= TW_CONTROL_MASK_COMMAND_INTERRUPT
;
1327 outl(control_reg_value
, control_reg_addr
);
1328 } /* End tw_mask_command_interrupt() */
1330 /* This function will poll the status register for a flag */
1331 int tw_poll_status(TW_Device_Extension
*tw_dev
, u32 flag
, int seconds
)
1333 u32 status_reg_addr
, status_reg_value
;
1334 struct timeval before
, timeout
;
1336 status_reg_addr
= tw_dev
->registers
.status_reg_addr
;
1337 do_gettimeofday(&before
);
1338 status_reg_value
= inl(status_reg_addr
);
1340 while ((status_reg_value
& flag
) != flag
) {
1341 status_reg_value
= inl(status_reg_addr
);
1342 do_gettimeofday(&timeout
);
1343 if (before
.tv_sec
+ seconds
< timeout
.tv_sec
) {
1344 printk(KERN_WARNING
"3w-xxxx: tw_poll_status(): Flag 0x%x not found.\n", flag
);
1350 } /* End tw_poll_status() */
1352 /* This function will attempt to post a command packet to the board */
1353 int tw_post_command_packet(TW_Device_Extension
*tw_dev
, int request_id
)
1355 u32 status_reg_addr
, status_reg_value
;
1356 u32 command_que_addr
, command_que_value
;
1358 dprintk(KERN_NOTICE
"3w-xxxx: tw_post_command_packet()\n");
1359 command_que_addr
= tw_dev
->registers
.command_que_addr
;
1360 command_que_value
= tw_dev
->command_packet_physical_address
[request_id
];
1361 status_reg_addr
= tw_dev
->registers
.status_reg_addr
;
1362 status_reg_value
= inl(status_reg_addr
);
1364 if (tw_check_bits(status_reg_value
))
1365 printk(KERN_WARNING
"3w-xxxx: tw_post_command_packet(): Unexpected bits.\n");
1367 if ((status_reg_value
& TW_STATUS_COMMAND_QUEUE_FULL
) == 0) {
1368 /* We successfully posted the command packet */
1369 outl(command_que_value
, command_que_addr
);
1370 tw_dev
->state
[request_id
] = TW_S_POSTED
;
1371 tw_dev
->posted_request_count
++;
1372 if (tw_dev
->posted_request_count
> tw_dev
->max_posted_request_count
) {
1373 tw_dev
->max_posted_request_count
= tw_dev
->posted_request_count
;
1376 /* Couldn't post the command packet, so we do it in the isr */
1377 if (tw_dev
->state
[request_id
] != TW_S_PENDING
) {
1378 tw_dev
->state
[request_id
] = TW_S_PENDING
;
1379 tw_dev
->pending_request_count
++;
1380 if (tw_dev
->pending_request_count
> tw_dev
->max_pending_request_count
) {
1381 tw_dev
->max_pending_request_count
= tw_dev
->pending_request_count
;
1383 tw_dev
->pending_queue
[tw_dev
->pending_tail
] = request_id
;
1384 if (tw_dev
->pending_tail
== TW_Q_LENGTH
-1) {
1385 tw_dev
->pending_tail
= TW_Q_START
;
1387 tw_dev
->pending_tail
= tw_dev
->pending_tail
+ 1;
1390 tw_unmask_command_interrupt(tw_dev
);
1394 } /* End tw_post_command_packet() */
1396 /* This function will reset a device extension */
1397 int tw_reset_device_extension(TW_Device_Extension
*tw_dev
)
1403 dprintk(KERN_NOTICE
"3w-xxxx: tw_reset_device_extension()\n");
1406 if (tw_reset_sequence(tw_dev
)) {
1407 printk(KERN_WARNING
"3w-xxxx: tw_reset_device_extension(): Reset sequence failed for card %d.\n", tw_dev
->host
->host_no
);
1411 /* Abort all requests that are in progress */
1412 for (i
=0;i
<imax
;i
++) {
1413 if ((tw_dev
->state
[i
] != TW_S_FINISHED
) &&
1414 (tw_dev
->state
[i
] != TW_S_INITIAL
) &&
1415 (tw_dev
->state
[i
] != TW_S_COMPLETED
)) {
1416 srb
= tw_dev
->srb
[i
];
1417 srb
->result
= (DID_RESET
<< 16);
1418 tw_dev
->srb
[i
]->scsi_done(tw_dev
->srb
[i
]);
1422 /* Reset queues and counts */
1423 for (i
=0;i
<imax
;i
++) {
1424 tw_dev
->free_queue
[i
] = i
;
1425 tw_dev
->state
[i
] = TW_S_INITIAL
;
1427 tw_dev
->free_head
= TW_Q_START
;
1428 tw_dev
->free_tail
= TW_Q_LENGTH
- 1;
1429 tw_dev
->posted_request_count
= 0;
1430 tw_dev
->pending_request_count
= 0;
1431 tw_dev
->pending_head
= TW_Q_START
;
1432 tw_dev
->pending_tail
= TW_Q_START
;
1435 } /* End tw_reset_device_extension() */
1437 /* This function will reset a controller */
1438 int tw_reset_sequence(TW_Device_Extension
*tw_dev
)
1443 /* Disable interrupts */
1444 tw_disable_interrupts(tw_dev
);
1446 /* Reset the board */
1447 while (tries
< TW_MAX_RESET_TRIES
) {
1448 tw_soft_reset(tw_dev
);
1450 error
= tw_aen_drain_queue(tw_dev
);
1452 printk(KERN_WARNING
"3w-xxxx: tw_reset_sequence(): No attention interrupt for card %d.\n", tw_dev
->host
->host_no
);
1457 /* Check for controller errors */
1458 if (tw_check_errors(tw_dev
)) {
1459 printk(KERN_WARNING
"3w-xxxx: tw_reset_sequence(): Controller errors found, soft resetting card %d.\n", tw_dev
->host
->host_no
);
1464 /* Empty the response queue again */
1465 error
= tw_empty_response_que(tw_dev
);
1467 printk(KERN_WARNING
"3w-xxxx: tw_reset_sequence(): Couldn't empty response queue for card %d.\n", tw_dev
->host
->host_no
);
1472 /* Now the controller is in a good state */
1476 if (tries
>= TW_MAX_RESET_TRIES
) {
1477 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
);
1481 error
= tw_initconnection(tw_dev
);
1483 printk(KERN_WARNING
"3w-xxxx: tw_reset_sequence(): Couldn't initconnection for card %d.\n", tw_dev
->host
->host_no
);
1487 /* Re-enable interrupts */
1488 tw_enable_interrupts(tw_dev
);
1491 } /* End tw_reset_sequence() */
1493 /* This funciton returns unit geometry in cylinders/heads/sectors */
1494 int tw_scsi_biosparam(Disk
*disk
, kdev_t dev
, int geom
[])
1496 int heads
, sectors
, cylinders
;
1497 TW_Device_Extension
*tw_dev
;
1499 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsi_biosparam()\n");
1500 tw_dev
= (TW_Device_Extension
*)disk
->device
->host
->hostdata
;
1504 cylinders
= disk
->capacity
/ (heads
* sectors
);
1506 if (disk
->capacity
>= 0x200000) {
1509 cylinders
= disk
->capacity
/ (heads
* sectors
);
1512 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsi_biosparam(): heads = %d, sectors = %d, cylinders = %d\n", heads
, sectors
, cylinders
);
1515 geom
[2] = cylinders
;
1518 } /* End tw_scsi_biosparam() */
1520 /* This function will find and initialize any cards */
1521 int tw_scsi_detect(Scsi_Host_Template
*tw_host
)
1523 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsi_detect()\n");
1525 /* Check if the kernel has PCI interface compiled in */
1526 if (!pci_present()) {
1527 printk(KERN_WARNING
"3w-xxxx: tw_scsi_detect(): No pci interface present.\n");
1531 return(tw_findcards(tw_host
));
1532 } /* End tw_scsi_detect() */
1534 /* This is the new scsi eh abort function */
1535 int tw_scsi_eh_abort(Scsi_Cmnd
*SCpnt
)
1537 TW_Device_Extension
*tw_dev
=NULL
;
1540 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsi_eh_abort()\n");
1543 printk(KERN_WARNING
"3w-xxxx: tw_scsi_eh_abort(): Invalid Scsi_Cmnd.\n");
1547 tw_dev
= (TW_Device_Extension
*)SCpnt
->host
->hostdata
;
1548 if (tw_dev
== NULL
) {
1549 printk(KERN_WARNING
"3w-xxxx: tw_scsi_eh_abort(): Invalid device extension.\n");
1553 spin_lock(&tw_dev
->tw_lock
);
1554 tw_dev
->num_aborts
++;
1556 /* If the command hasn't been posted yet, we can do the abort */
1557 for (i
=0;i
<TW_Q_LENGTH
;i
++) {
1558 if (tw_dev
->srb
[i
] == SCpnt
) {
1559 if (tw_dev
->state
[i
] == TW_S_STARTED
) {
1560 printk(KERN_WARNING
"3w-xxxx: tw_scsi_eh_abort(): Abort succeeded for started Scsi_Cmnd 0x%x\n", (u32
)tw_dev
->srb
[i
]);
1561 tw_dev
->state
[i
] = TW_S_COMPLETED
;
1562 tw_state_request_finish(tw_dev
, i
);
1563 spin_unlock(&tw_dev
->tw_lock
);
1566 if (tw_dev
->state
[i
] == TW_S_PENDING
) {
1567 printk(KERN_WARNING
"3w-xxxx: tw_scsi_eh_abort(): Abort succeeded for pending Scsi_Cmnd 0x%x\n", (u32
)tw_dev
->srb
[i
]);
1568 if (tw_dev
->pending_head
== TW_Q_LENGTH
-1) {
1569 tw_dev
->pending_head
= TW_Q_START
;
1571 tw_dev
->pending_head
= tw_dev
->pending_head
+ 1;
1573 tw_dev
->pending_request_count
--;
1574 tw_dev
->state
[i
] = TW_S_COMPLETED
;
1575 tw_state_request_finish(tw_dev
, i
);
1576 spin_unlock(&tw_dev
->tw_lock
);
1582 /* If the command has already been posted, we have to reset the card */
1583 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
);
1585 if (tw_reset_device_extension(tw_dev
)) {
1586 printk(KERN_WARNING
"3w-xxxx: tw_scsi_eh_abort(): Reset failed for card %d.\n", tw_dev
->host
->host_no
);
1587 spin_unlock(&tw_dev
->tw_lock
);
1590 spin_unlock(&tw_dev
->tw_lock
);
1593 } /* End tw_scsi_eh_abort() */
1595 /* This is the new scsi eh reset function */
1596 int tw_scsi_eh_reset(Scsi_Cmnd
*SCpnt
)
1598 TW_Device_Extension
*tw_dev
=NULL
;
1601 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsi_eh_reset()\n");
1604 printk(KERN_WARNING
"3w-xxxx: tw_scsi_eh_reset(): Invalid Scsi_Cmnd.\n");
1608 tw_dev
= (TW_Device_Extension
*)SCpnt
->host
->hostdata
;
1609 if (tw_dev
== NULL
) {
1610 printk(KERN_WARNING
"3w-xxxx: tw_scsi_eh_reset(): Invalid device extension.\n");
1614 spin_lock_irqsave(&tw_dev
->tw_lock
, flags
);
1615 tw_dev
->num_resets
++;
1617 /* Now reset the card and some of the device extension data */
1618 if (tw_reset_device_extension(tw_dev
)) {
1619 printk(KERN_WARNING
"3w-xxxx: tw_scsi_eh_reset(): Reset failed for card %d.\n", tw_dev
->host
->host_no
);
1620 spin_unlock_irqrestore(&tw_dev
->tw_lock
, flags
);
1623 printk(KERN_WARNING
"3w-xxxx: tw_scsi_eh_reset(): Reset succeeded for card %d.\n", tw_dev
->host
->host_no
);
1624 spin_unlock_irqrestore(&tw_dev
->tw_lock
, flags
);
1627 } /* End tw_scsi_eh_reset() */
1629 /* This function handles input and output from /proc/scsi/3w-xxxx/x */
1630 int tw_scsi_proc_info(char *buffer
, char **start
, off_t offset
, int length
, int hostno
, int inout
)
1632 TW_Device_Extension
*tw_dev
= NULL
;
1637 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsi_proc_info()\n");
1639 /* Find the correct device extension */
1640 for (i
=0;i
<tw_device_extension_count
;i
++)
1641 if (tw_device_extension_list
[i
]->host
->host_no
== hostno
)
1642 tw_dev
= tw_device_extension_list
[i
];
1643 if (tw_dev
== NULL
) {
1644 printk(KERN_WARNING
"3w-xxxx: tw_scsi_proc_info(): Couldn't locate device extension.\n");
1648 info
.buffer
= buffer
;
1649 info
.length
= length
;
1650 info
.offset
= offset
;
1655 if (strncmp(buffer
, "debug", 5) == 0) {
1656 printk(KERN_INFO
"3w-xxxx: Posted commands:\n");
1657 for (j
=0;j
<TW_Q_LENGTH
;j
++) {
1658 if (tw_dev
->state
[j
] == TW_S_POSTED
) {
1659 TW_Command
*command
= (TW_Command
*)tw_dev
->command_packet_virtual_address
[j
];
1660 printk(KERN_INFO
"3w-xxxx: Request_id: %d\n", j
);
1661 printk(KERN_INFO
"Opcode: 0x%x\n", command
->byte0
.opcode
);
1662 printk(KERN_INFO
"Block_count: 0x%x\n", command
->byte6
.block_count
);
1663 printk(KERN_INFO
"LBA: 0x%x\n", (u32
)command
->byte8
.io
.lba
);
1664 printk(KERN_INFO
"Physical command packet addr: 0x%x\n", tw_dev
->command_packet_physical_address
[j
]);
1665 printk(KERN_INFO
"Scsi_Cmnd: 0x%x\n", (u32
)tw_dev
->srb
[j
]);
1668 printk(KERN_INFO
"3w-xxxx: Free_head: %3d\n", tw_dev
->free_head
);
1669 printk(KERN_INFO
"3w-xxxx: Free_tail: %3d\n", tw_dev
->free_tail
);
1677 tw_copy_info(&info
, "scsi%d: 3ware Storage Controller\n", hostno
);
1678 tw_copy_info(&info
, "Driver version: %s\n", tw_driver_version
);
1679 tw_copy_info(&info
, "Current commands posted: %3d\n", tw_dev
->posted_request_count
);
1680 tw_copy_info(&info
, "Max commands posted: %3d\n", tw_dev
->max_posted_request_count
);
1681 tw_copy_info(&info
, "Current pending commands: %3d\n", tw_dev
->pending_request_count
);
1682 tw_copy_info(&info
, "Max pending commands: %3d\n", tw_dev
->max_pending_request_count
);
1683 tw_copy_info(&info
, "Last sgl length: %3d\n", tw_dev
->sgl_entries
);
1684 tw_copy_info(&info
, "Max sgl length: %3d\n", tw_dev
->max_sgl_entries
);
1685 tw_copy_info(&info
, "Last sector count: %3d\n", tw_dev
->sector_count
);
1686 tw_copy_info(&info
, "Max sector count: %3d\n", tw_dev
->max_sector_count
);
1687 tw_copy_info(&info
, "Resets: %3d\n", tw_dev
->num_resets
);
1688 tw_copy_info(&info
, "Aborts: %3d\n", tw_dev
->num_aborts
);
1690 if (info
.position
> info
.offset
) {
1691 return (info
.position
- info
.offset
);
1695 } /* End tw_scsi_proc_info() */
1697 /* This is the main scsi queue function to handle scsi opcodes */
1698 int tw_scsi_queue(Scsi_Cmnd
*SCpnt
, void (*done
)(Scsi_Cmnd
*))
1700 unsigned char *command
= SCpnt
->cmnd
;
1704 TW_Device_Extension
*tw_dev
= (TW_Device_Extension
*)SCpnt
->host
->hostdata
;
1706 spin_lock_irqsave(&tw_dev
->tw_lock
, flags
);
1707 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsi_queue()\n");
1709 /* Skip scsi command if it isn't for us */
1710 if ((tw_dev
->is_unit_present
[SCpnt
->target
] == FALSE
) || (SCpnt
->lun
!= 0)) {
1711 SCpnt
->result
= (DID_BAD_TARGET
<< 16);
1713 spin_unlock_irqrestore(&tw_dev
->tw_lock
, flags
);
1717 printk(KERN_WARNING
"3w-xxxx: tw_scsi_queue(): Invalid done function.\n");
1718 SCpnt
->result
= (DID_ERROR
<< 16);
1720 spin_unlock_irqrestore(&tw_dev
->tw_lock
, flags
);
1723 if (tw_dev
== NULL
) {
1724 printk(KERN_WARNING
"3w-xxxx: tw_scsi_queue(): Invalid device extension.\n");
1725 SCpnt
->result
= (DID_ERROR
<< 16);
1727 spin_unlock_irqrestore(&tw_dev
->tw_lock
, flags
);
1731 /* Save done function into Scsi_Cmnd struct */
1732 SCpnt
->scsi_done
= done
;
1734 /* Queue the command and get a request id */
1735 tw_state_request_start(tw_dev
, &request_id
);
1737 /* Save the scsi command for use by the ISR */
1738 tw_dev
->srb
[request_id
] = SCpnt
;
1742 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsi_queue(): caught READ_10.\n");
1744 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsi_queue(): caught READ_6.\n");
1746 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsi_queue(): caught WRITE_10.\n");
1748 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsi_queue(): caught WRITE_6.\n");
1749 error
= tw_scsiop_read_write(tw_dev
, request_id
);
1751 case TEST_UNIT_READY
:
1752 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsi_queue(): caught TEST_UNIT_READY.\n");
1753 error
= tw_scsiop_test_unit_ready(tw_dev
, request_id
);
1756 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsi_queue(): caught INQUIRY.\n");
1757 error
= tw_scsiop_inquiry(tw_dev
, request_id
);
1760 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsi_queue(): caught READ_CAPACITY.\n");
1761 error
= tw_scsiop_read_capacity(tw_dev
, request_id
);
1764 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsi_queue(): caught TW_SCSI_IOCTL.\n");
1765 error
= tw_ioctl(tw_dev
, request_id
);
1768 printk(KERN_NOTICE
"3w-xxxx: tw_scsi_queue(): Unknown scsi opcode: 0x%x\n", *command
);
1769 tw_dev
->state
[request_id
] = TW_S_COMPLETED
;
1770 tw_state_request_finish(tw_dev
, request_id
);
1771 SCpnt
->result
= (DID_BAD_TARGET
<< 16);
1775 tw_dev
->state
[request_id
] = TW_S_COMPLETED
;
1776 tw_state_request_finish(tw_dev
, request_id
);
1777 SCpnt
->result
= (DID_ERROR
<< 16);
1780 spin_unlock_irqrestore(&tw_dev
->tw_lock
, flags
);
1783 } /* End tw_scsi_queue() */
1785 /* This function will release the resources on an rmmod call */
1786 int tw_scsi_release(struct Scsi_Host
*tw_host
)
1788 TW_Device_Extension
*tw_dev
;
1789 tw_dev
= (TW_Device_Extension
*)tw_host
->hostdata
;
1791 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsi_release()\n");
1793 /* Free up the IO region */
1794 release_region((tw_dev
->tw_pci_dev
->resource
[0].start
), TW_IO_ADDRESS_RANGE
);
1796 /* Free up the IRQ */
1797 free_irq(tw_dev
->tw_pci_dev
->irq
, tw_dev
);
1799 /* Free up device extension resources */
1800 tw_free_device_extension(tw_dev
);
1802 /* Tell kernel scsi-layer we are gone */
1803 scsi_unregister(tw_host
);
1806 } /* End tw_scsi_release() */
1808 /* This function handles scsi inquiry commands */
1809 int tw_scsiop_inquiry(TW_Device_Extension
*tw_dev
, int request_id
)
1812 TW_Command
*command_packet
;
1813 u32 command_que_value
, command_que_addr
;
1816 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsiop_inquiry()\n");
1818 /* Initialize command packet */
1819 command_que_addr
= tw_dev
->registers
.command_que_addr
;
1820 command_packet
= (TW_Command
*)tw_dev
->command_packet_virtual_address
[request_id
];
1821 if (command_packet
== NULL
) {
1822 printk(KERN_WARNING
"3w-xxxx: tw_scsiop_inquiry(): Bad command packet virtual address.\n");
1825 memset(command_packet
, 0, sizeof(TW_Sector
));
1826 command_packet
->byte0
.opcode
= TW_OP_GET_PARAM
;
1827 command_packet
->byte0
.sgl_offset
= 2;
1828 command_packet
->size
= 4;
1829 command_packet
->request_id
= request_id
;
1830 command_packet
->byte3
.unit
= 0;
1831 command_packet
->byte3
.host_id
= 0;
1832 command_packet
->status
= 0;
1833 command_packet
->flags
= 0;
1834 command_packet
->byte6
.parameter_count
= 1;
1836 /* Now setup the param */
1837 if (tw_dev
->alignment_virtual_address
[request_id
] == NULL
) {
1838 printk(KERN_WARNING
"3w-xxxx: tw_scsiop_inquiry(): Bad alignment virtual address.\n");
1841 param
= (TW_Param
*)tw_dev
->alignment_virtual_address
[request_id
];
1842 memset(param
, 0, sizeof(TW_Sector
));
1843 param
->table_id
= 3; /* unit summary table */
1844 param
->parameter_id
= 3; /* unitsstatus parameter */
1845 param
->parameter_size_bytes
= TW_MAX_UNITS
;
1846 param_value
= tw_dev
->alignment_physical_address
[request_id
];
1847 if (param_value
== 0) {
1848 printk(KERN_WARNING
"3w-xxxx: tw_scsiop_inquiry(): Bad alignment physical address.\n");
1852 command_packet
->byte8
.param
.sgl
[0].address
= param_value
;
1853 command_packet
->byte8
.param
.sgl
[0].length
= sizeof(TW_Sector
);
1854 command_que_value
= tw_dev
->command_packet_physical_address
[request_id
];
1855 if (command_que_value
== 0) {
1856 printk(KERN_WARNING
"3w-xxxx: tw_scsiop_inquiry(): Bad command packet physical address.\n");
1860 /* Now try to post the command packet */
1861 tw_post_command_packet(tw_dev
, request_id
);
1864 } /* End tw_scsiop_inquiry() */
1866 /* This function is called by the isr to complete an inquiry command */
1867 int tw_scsiop_inquiry_complete(TW_Device_Extension
*tw_dev
, int request_id
)
1869 unsigned char *is_unit_present
;
1870 unsigned char *request_buffer
;
1874 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsiop_inquiry_complete()\n");
1876 /* Fill request buffer */
1877 if (tw_dev
->srb
[request_id
]->request_buffer
== NULL
) {
1878 printk(KERN_WARNING
"3w-xxxx: tw_scsiop_inquiry_complete(): Request buffer NULL.\n");
1881 request_buffer
= tw_dev
->srb
[request_id
]->request_buffer
;
1882 memset(request_buffer
, 0, tw_dev
->srb
[request_id
]->request_bufflen
);
1883 request_buffer
[0] = TYPE_DISK
; /* Peripheral device type */
1884 request_buffer
[1] = 0; /* Device type modifier */
1885 request_buffer
[2] = 0; /* No ansi/iso compliance */
1886 request_buffer
[4] = 31; /* Additional length */
1887 memcpy(&request_buffer
[8], "3ware ", 8); /* Vendor ID */
1888 memcpy(&request_buffer
[16], "3w-xxxx ", 16); /* Product ID */
1889 memcpy(&request_buffer
[32], tw_driver_version
, 3);
1891 param
= (TW_Param
*)tw_dev
->alignment_virtual_address
[request_id
];
1892 if (param
== NULL
) {
1893 printk(KERN_WARNING
"3w-xxxx: tw_scsiop_inquiry_complete(): Bad alignment virtual address.\n");
1896 is_unit_present
= &(param
->data
[0]);
1898 for (i
=0 ; i
<TW_MAX_UNITS
; i
++) {
1899 if (is_unit_present
[i
] == 0) {
1900 tw_dev
->is_unit_present
[i
] = FALSE
;
1902 tw_dev
->is_unit_present
[i
] = TRUE
;
1903 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsiop_inquiry_complete: Unit %d found.\n", i
);
1908 } /* End tw_scsiop_inquiry_complete() */
1910 /* This function handles scsi read_capacity commands */
1911 int tw_scsiop_read_capacity(TW_Device_Extension
*tw_dev
, int request_id
)
1914 TW_Command
*command_packet
;
1915 u32 command_que_addr
, command_que_value
;
1918 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsiop_read_capacity()\n");
1920 /* Initialize command packet */
1921 command_que_addr
= tw_dev
->registers
.command_que_addr
;
1922 command_packet
= (TW_Command
*)tw_dev
->command_packet_virtual_address
[request_id
];
1924 if (command_packet
== NULL
) {
1925 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsiop_read_capacity(): Bad command packet virtual address.\n");
1928 memset(command_packet
, 0, sizeof(TW_Sector
));
1929 command_packet
->byte0
.opcode
= TW_OP_GET_PARAM
;
1930 command_packet
->byte0
.sgl_offset
= 2;
1931 command_packet
->size
= 4;
1932 command_packet
->request_id
= request_id
;
1933 command_packet
->byte3
.unit
= tw_dev
->srb
[request_id
]->target
;
1934 command_packet
->byte3
.host_id
= 0;
1935 command_packet
->status
= 0;
1936 command_packet
->flags
= 0;
1937 command_packet
->byte6
.block_count
= 1;
1939 /* Now setup the param */
1940 if (tw_dev
->alignment_virtual_address
[request_id
] == NULL
) {
1941 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsiop_read_capacity(): Bad alignment virtual address.\n");
1944 param
= (TW_Param
*)tw_dev
->alignment_virtual_address
[request_id
];
1945 memset(param
, 0, sizeof(TW_Sector
));
1946 param
->table_id
= TW_UNIT_INFORMATION_TABLE_BASE
+
1947 tw_dev
->srb
[request_id
]->target
;
1948 param
->parameter_id
= 4; /* unitcapacity parameter */
1949 param
->parameter_size_bytes
= 4;
1950 param_value
= tw_dev
->alignment_physical_address
[request_id
];
1951 if (param_value
== 0) {
1952 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsiop_read_capacity(): Bad alignment physical address.\n");
1956 command_packet
->byte8
.param
.sgl
[0].address
= param_value
;
1957 command_packet
->byte8
.param
.sgl
[0].length
= sizeof(TW_Sector
);
1958 command_que_value
= tw_dev
->command_packet_physical_address
[request_id
];
1959 if (command_que_value
== 0) {
1960 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsiop_read_capacity(): Bad command packet physical address.\n");
1964 /* Now try to post the command to the board */
1965 tw_post_command_packet(tw_dev
, request_id
);
1968 } /* End tw_scsiop_read_capacity() */
1970 /* This function is called by the isr to complete a readcapacity command */
1971 int tw_scsiop_read_capacity_complete(TW_Device_Extension
*tw_dev
, int request_id
)
1973 unsigned char *param_data
;
1978 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsiop_read_capacity_complete()\n");
1980 buff
= tw_dev
->srb
[request_id
]->request_buffer
;
1982 printk(KERN_WARNING
"3w-xxxx: tw_scsiop_read_capacity_complete(): Request buffer NULL.\n");
1985 memset(buff
, 0, tw_dev
->srb
[request_id
]->request_bufflen
);
1986 param
= (TW_Param
*)tw_dev
->alignment_virtual_address
[request_id
];
1987 if (param
== NULL
) {
1988 printk(KERN_WARNING
"3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n");
1991 param_data
= &(param
->data
[0]);
1993 capacity
= (param_data
[3] << 24) | (param_data
[2] << 16) |
1994 (param_data
[1] << 8) | param_data
[0];
1996 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsiop_read_capacity_complete(): Capacity = 0x%x.\n", capacity
);
1998 /* Number of LBA's */
1999 buff
[0] = (capacity
>> 24);
2000 buff
[1] = (capacity
>> 16) & 0xff;
2001 buff
[2] = (capacity
>> 8) & 0xff;
2002 buff
[3] = capacity
& 0xff;
2004 /* Block size in bytes (512) */
2005 buff
[4] = (TW_BLOCK_SIZE
>> 24);
2006 buff
[5] = (TW_BLOCK_SIZE
>> 16) & 0xff;
2007 buff
[6] = (TW_BLOCK_SIZE
>> 8) & 0xff;
2008 buff
[7] = TW_BLOCK_SIZE
& 0xff;
2011 } /* End tw_scsiop_read_capacity_complete() */
2013 /* This function handles scsi read or write commands */
2014 int tw_scsiop_read_write(TW_Device_Extension
*tw_dev
, int request_id
)
2016 TW_Command
*command_packet
;
2017 u32 command_que_addr
, command_que_value
= 0;
2018 u32 lba
= 0x0, num_sectors
= 0x0;
2021 struct scatterlist
*sglist
;
2023 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsiop_read_write()\n");
2025 if (tw_dev
->srb
[request_id
]->request_buffer
== NULL
) {
2026 printk(KERN_WARNING
"3w-xxxx: tw_scsiop_read_write(): Request buffer NULL.\n");
2029 sglist
= (struct scatterlist
*)tw_dev
->srb
[request_id
]->request_buffer
;
2030 srb
= tw_dev
->srb
[request_id
];
2032 /* Initialize command packet */
2033 command_que_addr
= tw_dev
->registers
.command_que_addr
;
2034 command_packet
= (TW_Command
*)tw_dev
->command_packet_virtual_address
[request_id
];
2035 if (command_packet
== NULL
) {
2036 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsiop_read_write(): Bad command packet virtual address.\n");
2040 if (srb
->cmnd
[0] == READ_6
|| srb
->cmnd
[0] == READ_10
) {
2041 command_packet
->byte0
.opcode
= TW_OP_READ
;
2043 command_packet
->byte0
.opcode
= TW_OP_WRITE
;
2046 command_packet
->byte0
.sgl_offset
= 3;
2047 command_packet
->size
= 5;
2048 command_packet
->request_id
= request_id
;
2049 command_packet
->byte3
.unit
= srb
->target
;
2050 command_packet
->byte3
.host_id
= 0;
2051 command_packet
->status
= 0;
2052 command_packet
->flags
= 0;
2054 if ((srb
->cmnd
[0] == WRITE_6
) || (srb
->cmnd
[0] == WRITE_10
)) {
2055 if ((srb
->cmnd
[1] & 0x8) || (srb
->cmnd
[1] & 0x10))
2056 command_packet
->flags
= 1;
2059 if (srb
->cmnd
[0] == READ_6
|| srb
->cmnd
[0] == WRITE_6
) {
2060 lba
= ((u32
)srb
->cmnd
[1] << 16) | ((u32
)srb
->cmnd
[2] << 8) | (u32
)srb
->cmnd
[3];
2061 num_sectors
= (u32
)srb
->cmnd
[4];
2063 lba
= ((u32
)srb
->cmnd
[2] << 24) | ((u32
)srb
->cmnd
[3] << 16) | ((u32
)srb
->cmnd
[4] << 8) | (u32
)srb
->cmnd
[5];
2064 num_sectors
= (u32
)srb
->cmnd
[8] | ((u32
)srb
->cmnd
[7] << 8);
2067 /* Update sector statistic */
2068 tw_dev
->sector_count
= num_sectors
;
2069 if (tw_dev
->sector_count
> tw_dev
->max_sector_count
)
2070 tw_dev
->max_sector_count
= tw_dev
->sector_count
;
2072 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsiop_read_write(): lba = 0x%x num_sectors = 0x%x\n", lba
, num_sectors
);
2073 command_packet
->byte8
.io
.lba
= lba
;
2074 command_packet
->byte6
.block_count
= num_sectors
;
2076 /* Do this if there are no sg list entries */
2077 if (tw_dev
->srb
[request_id
]->use_sg
== 0) {
2078 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsiop_read_write(): SG = 0\n");
2079 command_packet
->byte8
.io
.sgl
[0].address
= virt_to_bus(tw_dev
->srb
[request_id
]->request_buffer
);
2080 command_packet
->byte8
.io
.sgl
[0].length
= tw_dev
->srb
[request_id
]->request_bufflen
;
2083 /* Do this if we have multiple sg list entries */
2084 if (tw_dev
->srb
[request_id
]->use_sg
> 0) {
2085 for (i
=0;i
<tw_dev
->srb
[request_id
]->use_sg
; i
++) {
2086 command_packet
->byte8
.io
.sgl
[i
].address
= virt_to_bus(sglist
[i
].address
);
2087 command_packet
->byte8
.io
.sgl
[i
].length
= sglist
[i
].length
;
2088 command_packet
->size
+=2;
2090 if (tw_dev
->srb
[request_id
]->use_sg
> 1)
2091 command_packet
->size
-=2;
2094 /* Update SG statistics */
2095 tw_dev
->sgl_entries
= tw_dev
->srb
[request_id
]->use_sg
;
2096 if (tw_dev
->sgl_entries
> tw_dev
->max_sgl_entries
)
2097 tw_dev
->max_sgl_entries
= tw_dev
->sgl_entries
;
2099 command_que_value
= tw_dev
->command_packet_physical_address
[request_id
];
2100 if (command_que_value
== 0) {
2101 dprintk(KERN_WARNING
"3w-xxxx: tw_scsiop_read_write(): Bad command packet physical address.\n");
2105 /* Now try to post the command to the board */
2106 tw_post_command_packet(tw_dev
, request_id
);
2109 } /* End tw_scsiop_read_write() */
2111 /* This function will handle test unit ready scsi command */
2112 int tw_scsiop_test_unit_ready(TW_Device_Extension
*tw_dev
, int request_id
)
2114 dprintk(KERN_NOTICE
"3w-xxxx: tw_scsiop_test_unit_ready()\n");
2116 /* Tell the scsi layer were done */
2117 tw_dev
->state
[request_id
] = TW_S_COMPLETED
;
2118 tw_state_request_finish(tw_dev
, request_id
);
2119 tw_dev
->srb
[request_id
]->result
= (DID_OK
<< 16);
2120 tw_dev
->srb
[request_id
]->scsi_done(tw_dev
->srb
[request_id
]);
2123 } /* End tw_scsiop_test_unit_ready() */
2125 /* This function will setup the interrupt handler */
2126 int tw_setup_irq(TW_Device_Extension
*tw_dev
)
2128 char *device
= TW_DEVICE_NAME
;
2131 dprintk(KERN_NOTICE
"3w-xxxx: tw_setup_irq()\n");
2132 error
= request_irq(tw_dev
->tw_pci_dev
->irq
, tw_interrupt
, SA_SHIRQ
, device
, tw_dev
);
2135 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
);
2139 } /* End tw_setup_irq() */
2141 /* This function will soft reset the controller */
2142 void tw_soft_reset(TW_Device_Extension
*tw_dev
)
2144 u32 control_reg_addr
, control_reg_value
;
2146 control_reg_addr
= tw_dev
->registers
.control_reg_addr
;
2147 control_reg_value
= ( TW_CONTROL_ISSUE_SOFT_RESET
|
2148 TW_CONTROL_CLEAR_HOST_INTERRUPT
|
2149 TW_CONTROL_CLEAR_ATTENTION_INTERRUPT
|
2150 TW_CONTROL_MASK_COMMAND_INTERRUPT
|
2151 TW_CONTROL_MASK_RESPONSE_INTERRUPT
|
2152 TW_CONTROL_CLEAR_ERROR_STATUS
|
2153 TW_CONTROL_DISABLE_INTERRUPTS
);
2154 outl(control_reg_value
, control_reg_addr
);
2155 } /* End tw_soft_reset() */
2157 /* This function will free a request_id */
2158 int tw_state_request_finish(TW_Device_Extension
*tw_dev
, int request_id
)
2160 dprintk(KERN_NOTICE
"3w-xxxx: tw_state_request_finish()\n");
2163 if (tw_dev
->free_tail
== TW_Q_LENGTH
-1) {
2164 tw_dev
->free_tail
= TW_Q_START
;
2166 tw_dev
->free_tail
= tw_dev
->free_tail
+ 1;
2168 } while ((tw_dev
->state
[tw_dev
->free_queue
[tw_dev
->free_tail
]] != TW_S_COMPLETED
));
2170 tw_dev
->free_queue
[tw_dev
->free_tail
] = request_id
;
2172 tw_dev
->state
[request_id
] = TW_S_FINISHED
;
2173 dprintk(KERN_NOTICE
"3w-xxxx: tw_state_request_finish(): Freeing request_id %d\n", request_id
);
2176 } /* End tw_state_request_finish() */
2178 /* This function will assign an available request_id */
2179 int tw_state_request_start(TW_Device_Extension
*tw_dev
, int *request_id
)
2183 dprintk(KERN_NOTICE
"3w-xxxx: tw_state_request_start()\n");
2185 /* Obtain next free request_id */
2187 if (tw_dev
->free_head
== TW_Q_LENGTH
- 1) {
2188 tw_dev
->free_head
= TW_Q_START
;
2190 tw_dev
->free_head
= tw_dev
->free_head
+ 1;
2192 } while ((tw_dev
->state
[tw_dev
->free_queue
[tw_dev
->free_head
]] == TW_S_STARTED
) ||
2193 (tw_dev
->state
[tw_dev
->free_queue
[tw_dev
->free_head
]] == TW_S_POSTED
) ||
2194 (tw_dev
->state
[tw_dev
->free_queue
[tw_dev
->free_head
]] == TW_S_PENDING
) ||
2195 (tw_dev
->state
[tw_dev
->free_queue
[tw_dev
->free_head
]] == TW_S_COMPLETED
));
2197 id
= tw_dev
->free_queue
[tw_dev
->free_head
];
2199 if (tw_dev
->free_head
== TW_Q_LENGTH
- 1) {
2200 tw_dev
->free_head
= TW_Q_START
;
2202 tw_dev
->free_head
= tw_dev
->free_head
+ 1;
2205 dprintk(KERN_NOTICE
"3w-xxxx: tw_state_request_start(): id = %d.\n", id
);
2207 tw_dev
->state
[id
] = TW_S_STARTED
;
2210 } /* End tw_state_request_start() */
2212 /* This function will unmask the command interrupt on the controller */
2213 void tw_unmask_command_interrupt(TW_Device_Extension
*tw_dev
)
2215 u32 control_reg_addr
, control_reg_value
;
2217 control_reg_addr
= tw_dev
->registers
.control_reg_addr
;
2218 control_reg_value
= TW_CONTROL_UNMASK_COMMAND_INTERRUPT
;
2219 outl(control_reg_value
, control_reg_addr
);
2220 } /* End tw_unmask_command_interrupt() */
2222 /* Now get things going */
2225 Scsi_Host_Template driver_template
= TWXXXX
;
2226 #include "scsi_module.c"