Import 2.3.48
[davej-history.git] / drivers / scsi / 3w-xxxx.c
blob42b86930db9cbc62ce71b36e55f0a643757aa0fd
1 /*
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.
21 NO WARRANTY
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:
46 linux@3ware.com
48 For more information, goto:
49 http://www.3ware.com
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>
71 #include <asm/io.h>
72 #include <asm/irq.h>
73 #include <asm/uaccess.h>
75 #define __3W_C /* let 3w-xxxx.h know it is use */
77 #include "sd.h"
78 #include "scsi.h"
79 #include "hosts.h"
81 #include "3w-xxxx.h"
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);
87 /* Globals */
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;
92 /* Functions */
94 /* This function will complete an aen request from the isr */
95 int tw_aen_complete(TW_Device_Extension *tw_dev, int request_id)
97 TW_Param *param;
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");
102 return 1;
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;
112 } else {
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;
118 } else {
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);
125 return 0;
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;
132 TW_Param *param;
133 int tries = 0;
134 int request_id = 0;
135 u32 command_que_value = 0, command_que_addr;
136 u32 status_reg_value = 0, status_reg_addr;
137 u32 param_value;
138 TW_Response_Queue response_queue;
139 u32 response_que_addr;
140 unsigned short aen;
141 unsigned short aen_code;
142 int finished = 0;
143 int first_reset = 0;
144 int queue = 0;
145 int imax, i;
146 int found = 0;
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);
156 return 1;
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");
162 return 1;
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");
178 return 1;
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");
184 return 1;
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");
194 return 1;
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 */
202 do {
203 /* Post command packet */
204 outl(command_que_value, command_que_addr);
206 /* Now poll for completion */
207 for (i=0;i<imax;i++) {
208 mdelay(10);
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");
212 return 1;
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");
221 return 1;
224 if (command_packet->status != 0) {
225 if (command_packet->flags != TW_AEN_TABLE_UNDEFINED) {
226 /* Bad response */
227 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad response, flags = 0x%x.\n", command_packet->flags);
228 return 1;
229 } else {
230 /* We know this is a 3w-1x00, and doesn't support aen's */
231 return 0;
235 /* Now check the aen */
236 aen = *(unsigned short *)(param->data);
237 aen_code = (aen & 0x0ff);
238 queue = 0;
239 switch (aen_code) {
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) {
243 continue;
244 } else {
245 finished = 1;
247 break;
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) {
251 first_reset = 1;
252 } else {
253 queue = 1;
255 break;
256 case TW_AEN_DEGRADED_MIRROR:
257 dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_DEGRADED_MIRROR.\n");
258 queue = 1;
259 break;
260 case TW_AEN_CONTROLLER_ERROR:
261 dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_CONTROLLER_ERROR.\n");
262 queue = 1;
263 break;
264 case TW_AEN_REBUILD_FAIL:
265 dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_REBUILD_FAIL.\n");
266 queue = 1;
267 break;
268 case TW_AEN_REBUILD_DONE:
269 dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_REBUILD_DONE.\n");
270 queue = 1;
271 break;
272 case TW_AEN_QUEUE_FULL:
273 dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue(): Found TW_AEN_QUEUE_FULL.\n");
274 queue = 1;
275 break;
276 default:
277 dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unknown AEN code 0x%x.\n", aen_code);
278 queue = 1;
281 /* Now put the aen on the aen_queue */
282 if (queue == 1) {
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;
286 } else {
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;
292 } else {
293 tw_dev->aen_head = tw_dev->aen_head + 1;
297 found = 1;
298 break;
301 if (found == 0) {
302 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Response never received.\n");
303 return 1;
305 tries++;
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");
310 return 1;
313 return 0;
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;
320 TW_Param *param;
321 u32 command_que_value = 0, command_que_addr;
322 u32 status_reg_value = 0, status_reg_addr;
323 u32 param_value = 0;
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");
332 return 1;
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");
336 return 1;
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");
352 return 1;
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");
357 return 1;
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");
367 return 1;
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);
378 } else {
379 printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Post failed, will retry.\n");
380 return 1;
383 return 0;
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)
389 u32 *virt_addr;
391 dprintk(KERN_NOTICE "3w-xxxx: tw_allocate_memory()\n");
393 if (which == 0) {
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");
398 return 1;
400 if ((u32)virt_addr % TW_ALIGNMENT) {
401 printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): Found unaligned address.\n");
402 return 1;
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);
407 } else {
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");
412 return 1;
414 if ((u32)virt_addr % TW_ALIGNMENT) {
415 printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): Found unaligned address.\n");
416 return 1;
418 tw_dev->alignment_virtual_address[request_id] = virt_addr;
419 tw_dev->alignment_physical_address[request_id] = virt_to_bus(virt_addr);
421 return 0;
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);
429 return 1;
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);
433 return 1;
436 return 0;
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))
448 return 1;
450 return 0;
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, ...)
476 va_list args;
477 char buf[81];
478 int len;
480 va_start(args, fmt);
481 len = vsprintf(buf, fmt, args);
482 va_end(args);
483 tw_copy_mem_info(info, buf, len);
484 return 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;
495 return;
497 if (info->position < info->offset) {
498 data += (info->offset - info->position);
499 len -= (info->offset - info->position);
501 if (len > 0) {
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");
530 return 1;
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");
538 return 1;
541 return 0;
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);
572 continue;
574 memset(tw_dev, 0, sizeof(TW_Device_Extension));
576 error = tw_initialize_device_extension(tw_dev);
577 if (error) {
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);
580 kfree(tw_dev);
581 continue;
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);
597 kfree(tw_dev);
598 continue;
601 /* Disable interrupts on the card */
602 tw_disable_interrupts(tw_dev);
604 while (tries < TW_MAX_RESET_TRIES) {
605 /* Do soft reset */
606 tw_soft_reset(tw_dev);
608 error = tw_aen_drain_queue(tw_dev);
609 if (error) {
610 printk(KERN_WARNING "3w-xxxx: tw_findcards(): No attention interrupt for card %d.\n", numcards);
611 tries++;
612 continue;
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);
618 tries++;
619 continue;
622 /* Empty the response queue */
623 error = tw_empty_response_que(tw_dev);
624 if (error) {
625 printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't empty response queue for card %d.\n", numcards);
626 tries++;
627 continue;
630 /* Now the controller is in a good state */
631 break;
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);
637 kfree(tw_dev);
638 continue;
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);
648 kfree(tw_dev);
649 continue;
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);
655 if (error) {
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);
659 kfree(tw_dev);
660 continue;
663 error = tw_initconnection(tw_dev);
664 if (error) {
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);
668 kfree(tw_dev);
669 continue;
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;
692 numcards++;
693 tw_device_extension_count = numcards;
694 tw_dev2->host = host;
695 } else {
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);
700 kfree(tw_dev);
701 continue;
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);
709 if (error) {
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);
715 kfree(tw_dev);
716 numcards--;
717 continue;
720 /* Free the temporary device extension */
721 if (tw_dev)
722 kfree(tw_dev);
725 if (numcards == 0)
726 printk(KERN_WARNING "3w-xxxx: tw_findcards(): No cards found.\n");
728 return numcards;
729 } /* End tw_findcards() */
731 /* This function will free up device extension resources */
732 void tw_free_device_extension(TW_Device_Extension *tw_dev)
734 int i, imax;
735 imax = TW_Q_LENGTH;
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;
756 int request_id = 0;
757 int i = 0;
758 int imax = 0;
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");
768 return 1;
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");
787 return 1;
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++) {
796 mdelay(10);
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");
800 return 1;
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");
808 return 1;
810 if (command_packet->status != 0) {
811 /* bad response */
812 printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad response, flags = 0x%x.\n", command_packet->flags);
813 return 1;
815 break; /* Response was okay, so we exit */
818 return 0;
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)
824 int i, imax;
826 dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_device_extension()\n");
827 imax = TW_Q_LENGTH;
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");
834 return 1;
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");
842 return 1;
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;
864 tw_dev->host = NULL;
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);
872 tw_dev->flags = 0;
873 return 0;
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)
879 int found = 0;
880 unsigned char request_id = 0;
881 TW_Command *command_packet;
882 TW_Param *param;
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;
888 u32 param_value;
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");
901 return 1;
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");
917 return 1;
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");
927 return 1;
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");
937 return 1;
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++) {
944 mdelay(10);
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");
948 return 1;
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");
956 return 1;
958 if (command_packet->status != 0) {
959 /* bad response */
960 printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, flags = 0x%x.\n", command_packet->flags);
961 return 1;
963 found = 1;
964 break;
967 if (found == 0) {
968 /* response never received */
969 printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): No response.\n");
970 return 1;
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 */
977 imax = TW_MAX_UNITS;
978 for(i=0; i<imax; i++) {
979 if (is_unit_present[i] == 0) {
980 tw_dev->is_unit_present[i] = FALSE;
981 } else {
982 dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_units(): Unit %d found.\n", i);
983 tw_dev->is_unit_present[i] = TRUE;
984 num_units++;
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");
991 return 1;
994 return 0;
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)
1000 int request_id;
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;
1005 int error = 0;
1006 int do_response_interrupt=0;
1007 int do_attention_interrupt=0;
1008 int do_host_interrupt=0;
1009 int do_command_interrupt=0;
1010 int flags = 0;
1011 int flags2 = 0;
1012 TW_Command *command_packet;
1013 if (test_and_set_bit(TW_IN_INTR, &tw_dev->flags))
1014 return;
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);
1047 if (error) {
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);
1051 } else {
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");
1064 break;
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;
1069 } else {
1070 tw_dev->pending_head = tw_dev->pending_head + 1;
1072 tw_dev->pending_request_count--;
1073 } else {
1074 break;
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);
1095 error = 0;
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);
1101 if (error) {
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");
1108 } else {
1109 switch (tw_dev->srb[request_id]->cmnd[0]) {
1110 case READ_10:
1111 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10\n");
1112 case READ_6:
1113 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_6\n");
1114 break;
1115 case WRITE_10:
1116 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10\n");
1117 case WRITE_6:
1118 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_6\n");
1119 break;
1120 case INQUIRY:
1121 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught INQUIRY\n");
1122 error = tw_scsiop_inquiry_complete(tw_dev, request_id);
1123 break;
1124 case READ_CAPACITY:
1125 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_CAPACITY\n");
1126 error = tw_scsiop_read_capacity_complete(tw_dev, request_id);
1127 break;
1128 case TW_IOCTL:
1129 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught TW_IOCTL\n");
1130 error = tw_ioctl_complete(tw_dev, request_id);
1131 break;
1132 default:
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]);
1137 if (error) {
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);
1141 } else {
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;
1166 int bufflen;
1167 TW_Param *param;
1168 TW_Command *command_packet;
1169 u32 param_value;
1170 TW_Ioctl *ioctl = NULL;
1171 int tw_aen_code;
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]);
1180 return 0;
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]);
1192 return 0;
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]);
1203 return 0;
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;
1211 switch (opcode) {
1212 case TW_OP_NOP:
1213 dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_NOP.\n");
1214 command_packet->byte0.opcode = TW_OP_NOP;
1215 break;
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);
1224 break;
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);
1233 break;
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);
1241 } else {
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;
1248 } else {
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]);
1256 return 0;
1257 default:
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]);
1263 return 0;
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);
1290 return 0;
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;
1298 TW_Param *param;
1300 dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete()\n");
1301 buff = tw_dev->srb[request_id]->request_buffer;
1302 if (buff == NULL) {
1303 printk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): Request buffer NULL.\n");
1304 return 1;
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");
1311 return 1;
1313 param_data = &(param->data[0]);
1315 memcpy(buff, param_data, tw_dev->ioctl_size[request_id]);
1317 return 0;
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);
1345 return 1;
1347 mdelay(1);
1349 return 0;
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;
1375 } else {
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;
1386 } else {
1387 tw_dev->pending_tail = tw_dev->pending_tail + 1;
1390 tw_unmask_command_interrupt(tw_dev);
1391 return 1;
1393 return 0;
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)
1399 int imax = 0;
1400 int i = 0;
1401 Scsi_Cmnd *srb;
1403 dprintk(KERN_NOTICE "3w-xxxx: tw_reset_device_extension()\n");
1404 imax = TW_Q_LENGTH;
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);
1408 return 1;
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;
1434 return 0;
1435 } /* End tw_reset_device_extension() */
1437 /* This function will reset a controller */
1438 int tw_reset_sequence(TW_Device_Extension *tw_dev)
1440 int error = 0;
1441 int tries = 0;
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);
1451 if (error) {
1452 printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): No attention interrupt for card %d.\n", tw_dev->host->host_no);
1453 tries++;
1454 continue;
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);
1460 tries++;
1461 continue;
1464 /* Empty the response queue again */
1465 error = tw_empty_response_que(tw_dev);
1466 if (error) {
1467 printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Couldn't empty response queue for card %d.\n", tw_dev->host->host_no);
1468 tries++;
1469 continue;
1472 /* Now the controller is in a good state */
1473 break;
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);
1478 return 1;
1481 error = tw_initconnection(tw_dev);
1482 if (error) {
1483 printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Couldn't initconnection for card %d.\n", tw_dev->host->host_no);
1484 return 1;
1487 /* Re-enable interrupts */
1488 tw_enable_interrupts(tw_dev);
1490 return 0;
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;
1502 heads = 64;
1503 sectors = 32;
1504 cylinders = disk->capacity / (heads * sectors);
1506 if (disk->capacity >= 0x200000) {
1507 heads = 255;
1508 sectors = 63;
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);
1513 geom[0] = heads;
1514 geom[1] = sectors;
1515 geom[2] = cylinders;
1517 return 0;
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");
1528 return 0;
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;
1538 int i = 0;
1540 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_eh_abort()\n");
1542 if (!SCpnt) {
1543 printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Invalid Scsi_Cmnd.\n");
1544 return (FAILED);
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");
1550 return (FAILED);
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);
1564 return (SUCCESS);
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;
1570 } else {
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);
1577 return (SUCCESS);
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);
1588 return (FAILED);
1590 spin_unlock(&tw_dev->tw_lock);
1592 return (SUCCESS);
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;
1599 int flags = 0;
1601 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_eh_reset()\n");
1603 if (!SCpnt) {
1604 printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Invalid Scsi_Cmnd.\n");
1605 return (FAILED);
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");
1611 return (FAILED);
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);
1621 return (FAILED);
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);
1626 return (SUCCESS);
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;
1633 TW_Info info;
1634 int i;
1635 int j;
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");
1645 return (-EINVAL);
1648 info.buffer = buffer;
1649 info.length = length;
1650 info.offset = offset;
1651 info.position = 0;
1653 if (inout) {
1654 /* Write */
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);
1671 return length;
1672 } else {
1673 /* Read */
1674 if (start) {
1675 *start = buffer;
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);
1692 } else {
1693 return 0;
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;
1701 int request_id = 0;
1702 int error = 0;
1703 int flags = 0;
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);
1712 done(SCpnt);
1713 spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
1714 return 0;
1716 if (done == NULL) {
1717 printk(KERN_WARNING "3w-xxxx: tw_scsi_queue(): Invalid done function.\n");
1718 SCpnt->result = (DID_ERROR << 16);
1719 done(SCpnt);
1720 spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
1721 return 0;
1723 if (tw_dev == NULL) {
1724 printk(KERN_WARNING "3w-xxxx: tw_scsi_queue(): Invalid device extension.\n");
1725 SCpnt->result = (DID_ERROR << 16);
1726 done(SCpnt);
1727 spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
1728 return 0;
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;
1740 switch (*command) {
1741 case READ_10:
1742 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_10.\n");
1743 case READ_6:
1744 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_6.\n");
1745 case WRITE_10:
1746 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught WRITE_10.\n");
1747 case WRITE_6:
1748 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught WRITE_6.\n");
1749 error = tw_scsiop_read_write(tw_dev, request_id);
1750 break;
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);
1754 break;
1755 case INQUIRY:
1756 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught INQUIRY.\n");
1757 error = tw_scsiop_inquiry(tw_dev, request_id);
1758 break;
1759 case READ_CAPACITY:
1760 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_CAPACITY.\n");
1761 error = tw_scsiop_read_capacity(tw_dev, request_id);
1762 break;
1763 case TW_IOCTL:
1764 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught TW_SCSI_IOCTL.\n");
1765 error = tw_ioctl(tw_dev, request_id);
1766 break;
1767 default:
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);
1772 done(SCpnt);
1774 if (error) {
1775 tw_dev->state[request_id] = TW_S_COMPLETED;
1776 tw_state_request_finish(tw_dev, request_id);
1777 SCpnt->result = (DID_ERROR << 16);
1778 done(SCpnt);
1780 spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
1782 return 0;
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);
1805 return 0;
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)
1811 TW_Param *param;
1812 TW_Command *command_packet;
1813 u32 command_que_value, command_que_addr;
1814 u32 param_value;
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");
1823 return 1;
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");
1839 return 1;
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");
1849 return 1;
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");
1857 return 1;
1860 /* Now try to post the command packet */
1861 tw_post_command_packet(tw_dev, request_id);
1863 return 0;
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;
1871 int i;
1872 TW_Param *param;
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");
1879 return 1;
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");
1894 return 1;
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;
1901 } else {
1902 tw_dev->is_unit_present[i] = TRUE;
1903 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete: Unit %d found.\n", i);
1907 return 0;
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)
1913 TW_Param *param;
1914 TW_Command *command_packet;
1915 u32 command_que_addr, command_que_value;
1916 u32 param_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");
1926 return 1;
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");
1942 return 1;
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");
1953 return 1;
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");
1961 return 1;
1964 /* Now try to post the command to the board */
1965 tw_post_command_packet(tw_dev, request_id);
1967 return 0;
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;
1974 u32 capacity;
1975 char *buff;
1976 TW_Param *param;
1978 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete()\n");
1980 buff = tw_dev->srb[request_id]->request_buffer;
1981 if (buff == NULL) {
1982 printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Request buffer NULL.\n");
1983 return 1;
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");
1989 return 1;
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;
2010 return 0;
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;
2019 int i;
2020 Scsi_Cmnd *srb;
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");
2027 return 1;
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");
2037 return 1;
2040 if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == READ_10) {
2041 command_packet->byte0.opcode = TW_OP_READ;
2042 } else {
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];
2062 } else {
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");
2102 return 1;
2105 /* Now try to post the command to the board */
2106 tw_post_command_packet(tw_dev, request_id);
2108 return 0;
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]);
2122 return 0;
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;
2129 int error;
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);
2134 if (error < 0) {
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);
2136 return 1;
2138 return 0;
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");
2162 do {
2163 if (tw_dev->free_tail == TW_Q_LENGTH-1) {
2164 tw_dev->free_tail = TW_Q_START;
2165 } else {
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);
2175 return 0;
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)
2181 int id = 0;
2183 dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_start()\n");
2185 /* Obtain next free request_id */
2186 do {
2187 if (tw_dev->free_head == TW_Q_LENGTH - 1) {
2188 tw_dev->free_head = TW_Q_START;
2189 } else {
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;
2201 } else {
2202 tw_dev->free_head = tw_dev->free_head + 1;
2205 dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_start(): id = %d.\n", id);
2206 *request_id = id;
2207 tw_dev->state[id] = TW_S_STARTED;
2209 return 0;
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 */
2224 #ifdef MODULE
2225 Scsi_Host_Template driver_template = TWXXXX;
2226 #include "scsi_module.c"
2227 #endif