aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/pci2000.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/pci2000.c')
-rw-r--r--drivers/scsi/pci2000.c836
1 files changed, 0 insertions, 836 deletions
diff --git a/drivers/scsi/pci2000.c b/drivers/scsi/pci2000.c
deleted file mode 100644
index 377a4666b568..000000000000
--- a/drivers/scsi/pci2000.c
+++ /dev/null
@@ -1,836 +0,0 @@
1/****************************************************************************
2 * Perceptive Solutions, Inc. PCI-2000 device driver for Linux.
3 *
4 * pci2000.c - Linux Host Driver for PCI-2000 IntelliCache SCSI Adapters
5 *
6 * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
7 * All Rights Reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that redistributions of source
11 * code retain the above copyright notice and this comment without
12 * modification.
13 *
14 * Technical updates and product information at:
15 * http://www.psidisk.com
16 *
17 * Please send questions, comments, bug reports to:
18 * tech@psidisk.com Technical Support
19 *
20 *
21 * Revisions 1.10 Jan-21-1999
22 * - Fixed sign on message to reflect proper controller name.
23 * - Added support for RAID status monitoring and control.
24 *
25 * Revisions 1.11 Mar-22-1999
26 * - Fixed control timeout to not lock up the entire system if
27 * controller goes offline completely.
28 *
29 * Revisions 1.12 Mar-26-1999
30 * - Fixed spinlock and PCI configuration.
31 *
32 * Revisions 1.20 Mar-27-2000
33 * - Added support for dynamic DMA
34 *
35 ****************************************************************************/
36#define PCI2000_VERSION "1.20"
37
38#include <linux/blkdev.h>
39#include <linux/interrupt.h>
40#include <linux/module.h>
41#include <linux/kernel.h>
42#include <linux/types.h>
43#include <linux/string.h>
44#include <linux/pci.h>
45#include <linux/ioport.h>
46#include <linux/delay.h>
47#include <linux/sched.h>
48#include <linux/proc_fs.h>
49#include <linux/stat.h>
50#include <linux/spinlock.h>
51
52#include <asm/dma.h>
53#include <asm/system.h>
54#include <asm/io.h>
55
56#include "scsi.h"
57#include <scsi/scsi_host.h>
58#include "pci2000.h"
59#include "psi_roy.h"
60
61
62//#define DEBUG 1
63
64#ifdef DEBUG
65#define DEB(x) x
66#define STOP_HERE {int st;for(st=0;st<100;st++){st=1;}}
67#else
68#define DEB(x)
69#define STOP_HERE
70#endif
71
72typedef struct
73 {
74 unsigned int address;
75 unsigned int length;
76 } SCATGATH, *PSCATGATH;
77
78typedef struct
79 {
80 Scsi_Cmnd *SCpnt;
81 PSCATGATH scatGath;
82 dma_addr_t scatGathDma;
83 UCHAR *cdb;
84 dma_addr_t cdbDma;
85 UCHAR tag;
86 } DEV2000, *PDEV2000;
87
88typedef struct
89 {
90 ULONG basePort;
91 ULONG mb0;
92 ULONG mb1;
93 ULONG mb2;
94 ULONG mb3;
95 ULONG mb4;
96 ULONG cmd;
97 ULONG tag;
98 ULONG irqOwned;
99 struct pci_dev *pdev;
100 DEV2000 dev[MAX_BUS][MAX_UNITS];
101 } ADAPTER2000, *PADAPTER2000;
102
103#define HOSTDATA(host) ((PADAPTER2000)&host->hostdata)
104#define consistentLen (MAX_BUS * MAX_UNITS * (16 * sizeof (SCATGATH) + MAX_COMMAND_SIZE))
105
106
107static struct Scsi_Host *PsiHost[MAXADAPTER] = {NULL,}; // One for each adapter
108static int NumAdapters = 0;
109/****************************************************************
110 * Name: WaitReady :LOCAL
111 *
112 * Description: Wait for controller ready.
113 *
114 * Parameters: padapter - Pointer adapter data structure.
115 *
116 * Returns: TRUE on not ready.
117 *
118 ****************************************************************/
119static int WaitReady (PADAPTER2000 padapter)
120 {
121 ULONG z;
122
123 for ( z = 0; z < (TIMEOUT_COMMAND * 4); z++ )
124 {
125 if ( !inb_p (padapter->cmd) )
126 return FALSE;
127 udelay (250);
128 };
129 return TRUE;
130 }
131/****************************************************************
132 * Name: WaitReadyLong :LOCAL
133 *
134 * Description: Wait for controller ready.
135 *
136 * Parameters: padapter - Pointer adapter data structure.
137 *
138 * Returns: TRUE on not ready.
139 *
140 ****************************************************************/
141static int WaitReadyLong (PADAPTER2000 padapter)
142 {
143 ULONG z;
144
145 for ( z = 0; z < (5000 * 4); z++ )
146 {
147 if ( !inb_p (padapter->cmd) )
148 return FALSE;
149 udelay (250);
150 };
151 return TRUE;
152 }
153/****************************************************************
154 * Name: OpDone :LOCAL
155 *
156 * Description: Clean up operation and issue done to caller.
157 *
158 * Parameters: SCpnt - Pointer to SCSI command structure.
159 * status - Caller status.
160 *
161 * Returns: Nothing.
162 *
163 ****************************************************************/
164static void OpDone (Scsi_Cmnd *SCpnt, ULONG status)
165 {
166 SCpnt->result = status;
167 SCpnt->scsi_done (SCpnt);
168 }
169/****************************************************************
170 * Name: Command :LOCAL
171 *
172 * Description: Issue queued command to the PCI-2000.
173 *
174 * Parameters: padapter - Pointer to adapter information structure.
175 * cmd - PCI-2000 command byte.
176 *
177 * Returns: Non-zero command tag if operation is accepted.
178 *
179 ****************************************************************/
180static UCHAR Command (PADAPTER2000 padapter, UCHAR cmd)
181 {
182 outb_p (cmd, padapter->cmd);
183 if ( WaitReady (padapter) )
184 return 0;
185
186 if ( inw_p (padapter->mb0) )
187 return 0;
188
189 return inb_p (padapter->mb1);
190 }
191/****************************************************************
192 * Name: BuildSgList :LOCAL
193 *
194 * Description: Build the scatter gather list for controller.
195 *
196 * Parameters: SCpnt - Pointer to SCSI command structure.
197 * padapter - Pointer to adapter information structure.
198 * pdev - Pointer to adapter device structure.
199 *
200 * Returns: Non-zero in not scatter gather.
201 *
202 ****************************************************************/
203static int BuildSgList (Scsi_Cmnd *SCpnt, PADAPTER2000 padapter, PDEV2000 pdev)
204 {
205 int z;
206 int zc;
207 struct scatterlist *sg;
208
209 if ( SCpnt->use_sg )
210 {
211 sg = (struct scatterlist *)SCpnt->request_buffer;
212 zc = pci_map_sg (padapter->pdev, sg, SCpnt->use_sg, SCpnt->sc_data_direction);
213 for ( z = 0; z < zc; z++ )
214 {
215 pdev->scatGath[z].address = cpu_to_le32 (sg_dma_address (sg));
216 pdev->scatGath[z].length = cpu_to_le32 (sg_dma_len (sg++));
217 }
218 outl (pdev->scatGathDma, padapter->mb2);
219 outl ((zc << 24) | SCpnt->request_bufflen, padapter->mb3);
220 return FALSE;
221 }
222 if ( !SCpnt->request_bufflen)
223 {
224 outl (0, padapter->mb2);
225 outl (0, padapter->mb3);
226 return TRUE;
227 }
228 SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev,
229 SCpnt->request_buffer, SCpnt->request_bufflen,
230 SCpnt->sc_data_direction);
231 outl (SCpnt->SCp.have_data_in, padapter->mb2);
232 outl (SCpnt->request_bufflen, padapter->mb3);
233 return TRUE;
234 }
235/*********************************************************************
236 * Name: PsiRaidCmd
237 *
238 * Description: Execute a simple command.
239 *
240 * Parameters: padapter - Pointer to adapter control structure.
241 * cmd - Roy command byte.
242 *
243 * Returns: Return error status.
244 *
245 ********************************************************************/
246static int PsiRaidCmd (PADAPTER2000 padapter, char cmd)
247 {
248 if ( WaitReady (padapter) ) // test for command register ready
249 return DID_TIME_OUT;
250 outb_p (cmd, padapter->cmd); // issue command
251 if ( WaitReadyLong (padapter) ) // wait for adapter ready
252 return DID_TIME_OUT;
253 return DID_OK;
254 }
255/****************************************************************
256 * Name: Irq_Handler :LOCAL
257 *
258 * Description: Interrupt handler.
259 *
260 * Parameters: irq - Hardware IRQ number.
261 * dev_id -
262 * regs -
263 *
264 * Returns: TRUE if drive is not ready in time.
265 *
266 ****************************************************************/
267static irqreturn_t Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
268 {
269 struct Scsi_Host *shost = NULL; // Pointer to host data block
270 PADAPTER2000 padapter; // Pointer to adapter control structure
271 PDEV2000 pdev;
272 Scsi_Cmnd *SCpnt;
273 UCHAR tag = 0;
274 UCHAR tag0;
275 ULONG error;
276 int pun;
277 int bus;
278 int z;
279 unsigned long flags;
280 int handled = 0;
281
282 DEB(printk ("\npci2000 received interrupt "));
283 for ( z = 0; z < NumAdapters; z++ ) // scan for interrupt to process
284 {
285 if ( PsiHost[z]->irq == (UCHAR)(irq & 0xFF) )
286 {
287 tag = inb_p (HOSTDATA(PsiHost[z])->tag);
288 if ( tag )
289 {
290 shost = PsiHost[z];
291 break;
292 }
293 }
294 }
295
296 if ( !shost )
297 {
298 DEB (printk ("\npci2000: not my interrupt"));
299 goto out;
300 }
301
302 handled = 1;
303 spin_lock_irqsave(shost->host_lock, flags);
304 padapter = HOSTDATA(shost);
305
306 tag0 = tag & 0x7F; // mask off the error bit
307 for ( bus = 0; bus < MAX_BUS; bus++ ) // scan the busses
308 {
309 for ( pun = 0; pun < MAX_UNITS; pun++ ) // scan the targets
310 {
311 pdev = &padapter->dev[bus][pun];
312 if ( !pdev->tag )
313 continue;
314 if ( pdev->tag == tag0 ) // is this it?
315 {
316 pdev->tag = 0;
317 SCpnt = pdev->SCpnt;
318 goto unmapProceed;
319 }
320 }
321 }
322
323 outb_p (0xFF, padapter->tag); // clear the op interrupt
324 outb_p (CMD_DONE, padapter->cmd); // complete the op
325 goto irq_return; // done, but, with what?
326
327unmapProceed:;
328 if ( !bus )
329 {
330 switch ( SCpnt->cmnd[0] )
331 {
332 case SCSIOP_TEST_UNIT_READY:
333 pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, sizeof (SCpnt->sense_buffer), PCI_DMA_FROMDEVICE);
334 goto irqProceed;
335 case SCSIOP_READ_CAPACITY:
336 pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, 8, PCI_DMA_FROMDEVICE);
337 goto irqProceed;
338 case SCSIOP_VERIFY:
339 case SCSIOP_START_STOP_UNIT:
340 case SCSIOP_MEDIUM_REMOVAL:
341 goto irqProceed;
342 }
343 }
344 if ( SCpnt->SCp.have_data_in )
345 pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, SCpnt->request_bufflen, SCpnt->sc_data_direction);
346 else
347 {
348 if ( SCpnt->use_sg )
349 pci_unmap_sg (padapter->pdev, (struct scatterlist *)SCpnt->request_buffer, SCpnt->use_sg, SCpnt->sc_data_direction);
350 }
351
352irqProceed:;
353 if ( tag & ERR08_TAGGED ) // is there an error here?
354 {
355 if ( WaitReady (padapter) )
356 {
357 OpDone (SCpnt, DID_TIME_OUT << 16);
358 goto irq_return;
359 }
360
361 outb_p (tag0, padapter->mb0); // get real error code
362 outb_p (CMD_ERROR, padapter->cmd);
363 if ( WaitReady (padapter) ) // wait for controller to suck up the op
364 {
365 OpDone (SCpnt, DID_TIME_OUT << 16);
366 goto irq_return;
367 }
368
369 error = inl (padapter->mb0); // get error data
370 outb_p (0xFF, padapter->tag); // clear the op interrupt
371 outb_p (CMD_DONE, padapter->cmd); // complete the op
372
373 DEB (printk ("status: %lX ", error));
374 if ( error == 0x00020002 ) // is this error a check condition?
375 {
376 if ( bus ) // are we doint SCSI commands?
377 {
378 OpDone (SCpnt, (DID_OK << 16) | 2);
379 goto irq_return;
380 }
381 if ( *SCpnt->cmnd == SCSIOP_TEST_UNIT_READY )
382 OpDone (SCpnt, (DRIVER_SENSE << 24) | (DID_OK << 16) | 2); // test caller we have sense data too
383 else
384 OpDone (SCpnt, DID_ERROR << 16);
385 goto irq_return;
386 }
387 OpDone (SCpnt, DID_ERROR << 16);
388 goto irq_return;
389 }
390
391 outb_p (0xFF, padapter->tag); // clear the op interrupt
392 outb_p (CMD_DONE, padapter->cmd); // complete the op
393 OpDone (SCpnt, DID_OK << 16);
394
395irq_return:
396 spin_unlock_irqrestore(shost->host_lock, flags);
397out:
398 return IRQ_RETVAL(handled);
399}
400/****************************************************************
401 * Name: Pci2000_QueueCommand
402 *
403 * Description: Process a queued command from the SCSI manager.
404 *
405 * Parameters: SCpnt - Pointer to SCSI command structure.
406 * done - Pointer to done function to call.
407 *
408 * Returns: Status code.
409 *
410 ****************************************************************/
411int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
412 {
413 UCHAR *cdb = (UCHAR *)SCpnt->cmnd; // Pointer to SCSI CDB
414 PADAPTER2000 padapter = HOSTDATA(SCpnt->device->host); // Pointer to adapter control structure
415 int rc = -1; // command return code
416 UCHAR bus = SCpnt->device->channel;
417 UCHAR pun = SCpnt->device->id;
418 UCHAR lun = SCpnt->device->lun;
419 UCHAR cmd;
420 PDEV2000 pdev = &padapter->dev[bus][pun];
421
422 if ( !done )
423 {
424 printk("pci2000_queuecommand: %02X: done can't be NULL\n", *cdb);
425 return 0;
426 }
427
428 SCpnt->scsi_done = done;
429 SCpnt->SCp.have_data_in = 0;
430 pdev->SCpnt = SCpnt; // Save this command data
431
432 if ( WaitReady (padapter) )
433 {
434 rc = DID_ERROR;
435 goto finished;
436 }
437
438 outw_p (pun | (lun << 8), padapter->mb0);
439
440 if ( bus )
441 {
442 DEB (if(*cdb) printk ("\nCDB: %X- %X %X %X %X %X %X %X %X %X %X ", SCpnt->cmd_len, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9]));
443 DEB (if(*cdb) printk ("\ntimeout_per_command: %d, timeout_total: %d, timeout: %d", SCpnt->timeout_per_command,
444 SCpnt->timeout_total, SCpnt->timeout));
445 outl (SCpnt->timeout_per_command, padapter->mb1);
446 outb_p (CMD_SCSI_TIMEOUT, padapter->cmd);
447 if ( WaitReady (padapter) )
448 {
449 rc = DID_ERROR;
450 goto finished;
451 }
452
453 outw_p (pun | (lun << 8), padapter->mb0);
454 outw_p (SCpnt->cmd_len << 8, padapter->mb0 + 2);
455 memcpy (pdev->cdb, cdb, MAX_COMMAND_SIZE);
456
457 outl (pdev->cdbDma, padapter->mb1);
458 if ( BuildSgList (SCpnt, padapter, pdev) )
459 cmd = CMD_SCSI_THRU;
460 else
461 cmd = CMD_SCSI_THRU_SG;
462 if ( (pdev->tag = Command (padapter, cmd)) == 0 )
463 rc = DID_TIME_OUT;
464 goto finished;
465 }
466 else
467 {
468 if ( lun )
469 {
470 rc = DID_BAD_TARGET;
471 goto finished;
472 }
473 }
474
475 switch ( *cdb )
476 {
477 case SCSIOP_INQUIRY: // inquiry CDB
478 if ( cdb[2] == SC_MY_RAID )
479 {
480 switch ( cdb[3] )
481 {
482 case MY_SCSI_REBUILD:
483 OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_REBUILD) << 16);
484 return 0;
485 case MY_SCSI_ALARMMUTE:
486 OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_MUTE) << 16);
487 return 0;
488 case MY_SCSI_DEMOFAIL:
489 OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_FAIL) << 16);
490 return 0;
491 default:
492 if ( SCpnt->use_sg )
493 {
494 rc = DID_ERROR;
495 goto finished;
496 }
497 else
498 {
499 SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, SCpnt->request_bufflen,
500 SCpnt->sc_data_direction);
501 outl (SCpnt->SCp.have_data_in, padapter->mb2);
502 }
503 outl (cdb[5], padapter->mb0);
504 outl (cdb[3], padapter->mb3);
505 cmd = CMD_DASD_RAID_RQ;
506 break;
507 }
508 break;
509 }
510
511 if ( SCpnt->use_sg )
512 {
513 SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev,
514 ((struct scatterlist *)SCpnt->request_buffer)->address,
515 SCpnt->request_bufflen,
516 SCpnt->sc_data_direction);
517 }
518 else
519 {
520 SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer,
521 SCpnt->request_bufflen,
522 SCpnt->sc_data_direction);
523 }
524 outl (SCpnt->SCp.have_data_in, padapter->mb2);
525 outl (SCpnt->request_bufflen, padapter->mb3);
526 cmd = CMD_DASD_SCSI_INQ;
527 break;
528
529 case SCSIOP_TEST_UNIT_READY: // test unit ready CDB
530 SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->sense_buffer, sizeof (SCpnt->sense_buffer), PCI_DMA_FROMDEVICE);
531 outl (SCpnt->SCp.have_data_in, padapter->mb2);
532 outl (sizeof (SCpnt->sense_buffer), padapter->mb3);
533 cmd = CMD_TEST_READY;
534 break;
535
536 case SCSIOP_READ_CAPACITY: // read capacity CDB
537 if ( SCpnt->use_sg )
538 {
539 SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, ((struct scatterlist *)(SCpnt->request_buffer))->address,
540 8, PCI_DMA_FROMDEVICE);
541 }
542 else
543 SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, 8, PCI_DMA_FROMDEVICE);
544 outl (SCpnt->SCp.have_data_in, padapter->mb2);
545 outl (8, padapter->mb3);
546 cmd = CMD_DASD_CAP;
547 break;
548 case SCSIOP_VERIFY: // verify CDB
549 outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
550 outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
551 cmd = CMD_READ_SG;
552 break;
553 case SCSIOP_READ: // read10 CDB
554 outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
555 outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
556 if ( BuildSgList (SCpnt, padapter, pdev) )
557 cmd = CMD_READ;
558 else
559 cmd = CMD_READ_SG;
560 break;
561 case SCSIOP_READ6: // read6 CDB
562 outw_p (cdb[4], padapter->mb0 + 2);
563 outl ((SCSI2LONG (&cdb[1])) & 0x001FFFFF, padapter->mb1);
564 if ( BuildSgList (SCpnt, padapter, pdev) )
565 cmd = CMD_READ;
566 else
567 cmd = CMD_READ_SG;
568 break;
569 case SCSIOP_WRITE: // write10 CDB
570 outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
571 outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
572 if ( BuildSgList (SCpnt, padapter, pdev) )
573 cmd = CMD_WRITE;
574 else
575 cmd = CMD_WRITE_SG;
576 break;
577 case SCSIOP_WRITE6: // write6 CDB
578 outw_p (cdb[4], padapter->mb0 + 2);
579 outl ((SCSI2LONG (&cdb[1])) & 0x001FFFFF, padapter->mb1);
580 if ( BuildSgList (SCpnt, padapter, pdev) )
581 cmd = CMD_WRITE;
582 else
583 cmd = CMD_WRITE_SG;
584 break;
585 case SCSIOP_START_STOP_UNIT:
586 cmd = CMD_EJECT_MEDIA;
587 break;
588 case SCSIOP_MEDIUM_REMOVAL:
589 switch ( cdb[4] )
590 {
591 case 0:
592 cmd = CMD_UNLOCK_DOOR;
593 break;
594 case 1:
595 cmd = CMD_LOCK_DOOR;
596 break;
597 default:
598 cmd = 0;
599 break;
600 }
601 if ( cmd )
602 break;
603 default:
604 DEB (printk ("pci2000_queuecommand: Unsupported command %02X\n", *cdb));
605 OpDone (SCpnt, DID_ERROR << 16);
606 return 0;
607 }
608
609 if ( (pdev->tag = Command (padapter, cmd)) == 0 )
610 rc = DID_TIME_OUT;
611finished:;
612 if ( rc != -1 )
613 OpDone (SCpnt, rc << 16);
614 return 0;
615 }
616/****************************************************************
617 * Name: Pci2000_Detect
618 *
619 * Description: Detect and initialize our boards.
620 *
621 * Parameters: tpnt - Pointer to SCSI host template structure.
622 *
623 * Returns: Number of adapters installed.
624 *
625 ****************************************************************/
626int Pci2000_Detect (Scsi_Host_Template *tpnt)
627 {
628 int found = 0;
629 int installed = 0;
630 struct Scsi_Host *pshost;
631 PADAPTER2000 padapter;
632 int z, zz;
633 int setirq;
634 struct pci_dev *pdev = NULL;
635 UCHAR *consistent;
636 dma_addr_t consistentDma;
637
638 while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_ROY_1, pdev)) != NULL )
639 {
640 if (pci_enable_device(pdev))
641 continue;
642 pshost = scsi_register (tpnt, sizeof(ADAPTER2000));
643 if(pshost == NULL)
644 continue;
645 padapter = HOSTDATA(pshost);
646
647 padapter->basePort = pci_resource_start (pdev, 1);
648 DEB (printk ("\nBase Regs = %#04X", padapter->basePort)); // get the base I/O port address
649 padapter->mb0 = padapter->basePort + RTR_MAILBOX; // get the 32 bit mail boxes
650 padapter->mb1 = padapter->basePort + RTR_MAILBOX + 4;
651 padapter->mb2 = padapter->basePort + RTR_MAILBOX + 8;
652 padapter->mb3 = padapter->basePort + RTR_MAILBOX + 12;
653 padapter->mb4 = padapter->basePort + RTR_MAILBOX + 16;
654 padapter->cmd = padapter->basePort + RTR_LOCAL_DOORBELL; // command register
655 padapter->tag = padapter->basePort + RTR_PCI_DOORBELL; // tag/response register
656 padapter->pdev = pdev;
657
658 if ( WaitReady (padapter) )
659 goto unregister;
660 outb_p (0x84, padapter->mb0);
661 outb_p (CMD_SPECIFY, padapter->cmd);
662 if ( WaitReady (padapter) )
663 goto unregister;
664
665 consistent = pci_alloc_consistent (pdev, consistentLen, &consistentDma);
666 if ( !consistent )
667 {
668 printk ("Unable to allocate DMA memory for PCI-2000 controller.\n");
669 goto unregister;
670 }
671
672 scsi_set_device(pshost, &pdev->dev);
673 pshost->irq = pdev->irq;
674 setirq = 1;
675 padapter->irqOwned = 0;
676 for ( z = 0; z < installed; z++ ) // scan for shared interrupts
677 {
678 if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses
679 setirq = 0;
680 }
681 if ( setirq ) // if not shared, posses
682 {
683 if ( request_irq (pshost->irq, Irq_Handler, SA_SHIRQ, "pci2000", padapter) < 0 )
684 {
685 if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2000", padapter) < 0 )
686 {
687 printk ("Unable to allocate IRQ for PCI-2000 controller.\n");
688 pci_free_consistent (pdev, consistentLen, consistent, consistentDma);
689 goto unregister;
690 }
691 }
692 padapter->irqOwned = pshost->irq; // set IRQ as owned
693 }
694 PsiHost[installed] = pshost; // save SCSI_HOST pointer
695
696 pshost->io_port = padapter->basePort;
697 pshost->n_io_port = 0xFF;
698 pshost->unique_id = padapter->basePort;
699 pshost->max_id = 16;
700 pshost->max_channel = 1;
701
702 for ( zz = 0; zz < MAX_BUS; zz++ )
703 for ( z = 0; z < MAX_UNITS; z++ )
704 {
705 padapter->dev[zz][z].tag = 0;
706 padapter->dev[zz][z].scatGath = (PSCATGATH)consistent;
707 padapter->dev[zz][z].scatGathDma = consistentDma;
708 consistent += 16 * sizeof (SCATGATH);
709 consistentDma += 16 * sizeof (SCATGATH);
710 padapter->dev[zz][z].cdb = (UCHAR *)consistent;
711 padapter->dev[zz][z].cdbDma = consistentDma;
712 consistent += MAX_COMMAND_SIZE;
713 consistentDma += MAX_COMMAND_SIZE;
714 }
715
716 printk("\nPSI-2000 Intelligent Storage SCSI CONTROLLER: at I/O = %lX IRQ = %d\n", padapter->basePort, pshost->irq);
717 printk("Version %s, Compiled %s %s\n\n", PCI2000_VERSION, __DATE__, __TIME__);
718 found++;
719 if ( ++installed < MAXADAPTER )
720 continue;
721 break;
722unregister:;
723 scsi_unregister (pshost);
724 found++;
725 }
726 NumAdapters = installed;
727 return installed;
728 }
729/****************************************************************
730 * Name: Pci2000_Abort
731 *
732 * Description: Process the Abort command from the SCSI manager.
733 *
734 * Parameters: SCpnt - Pointer to SCSI command structure.
735 *
736 * Returns: Allways snooze.
737 *
738 ****************************************************************/
739int Pci2000_Abort (Scsi_Cmnd *SCpnt)
740 {
741 DEB (printk ("pci2000_abort\n"));
742 return SCSI_ABORT_SNOOZE;
743 }
744/****************************************************************
745 * Name: Pci2000_Reset
746 *
747 * Description: Process the Reset command from the SCSI manager.
748 *
749 * Parameters: SCpnt - Pointer to SCSI command structure.
750 * flags - Flags about the reset command
751 *
752 * Returns: No active command at this time, so this means
753 * that each time we got some kind of response the
754 * last time through. Tell the mid-level code to
755 * request sense information in order to decide what
756 * to do next.
757 *
758 ****************************************************************/
759int Pci2000_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
760 {
761 return SCSI_RESET_PUNT;
762 }
763/****************************************************************
764 * Name: Pci2000_Release
765 *
766 * Description: Release resources allocated for a single each adapter.
767 *
768 * Parameters: pshost - Pointer to SCSI command structure.
769 *
770 * Returns: zero.
771 *
772 ****************************************************************/
773int Pci2000_Release (struct Scsi_Host *pshost)
774 {
775 PADAPTER2000 padapter = HOSTDATA (pshost);
776
777 if ( padapter->irqOwned )
778 free_irq (pshost->irq, padapter);
779 pci_free_consistent (padapter->pdev, consistentLen, padapter->dev[0][0].scatGath, padapter->dev[0][0].scatGathDma);
780 release_region (pshost->io_port, pshost->n_io_port);
781 scsi_unregister(pshost);
782 return 0;
783 }
784
785/****************************************************************
786 * Name: Pci2000_BiosParam
787 *
788 * Description: Process the biosparam request from the SCSI manager to
789 * return C/H/S data.
790 *
791 * Parameters: disk - Pointer to SCSI disk structure.
792 * dev - Major/minor number from kernel.
793 * geom - Pointer to integer array to place geometry data.
794 *
795 * Returns: zero.
796 *
797 ****************************************************************/
798int Pci2000_BiosParam (struct scsi_device *sdev, struct block_device *dev,
799 sector_t capacity, int geom[])
800 {
801 PADAPTER2000 padapter;
802
803 padapter = HOSTDATA(sdev->host);
804
805 if ( WaitReady (padapter) )
806 return 0;
807 outb_p (sdev->id, padapter->mb0);
808 outb_p (CMD_GET_PARMS, padapter->cmd);
809 if ( WaitReady (padapter) )
810 return 0;
811
812 geom[0] = inb_p (padapter->mb2 + 3);
813 geom[1] = inb_p (padapter->mb2 + 2);
814 geom[2] = inw_p (padapter->mb2);
815 return 0;
816 }
817
818
819MODULE_LICENSE("Dual BSD/GPL");
820
821static Scsi_Host_Template driver_template = {
822 .proc_name = "pci2000",
823 .name = "PCI-2000 SCSI Intelligent Disk Controller",
824 .detect = Pci2000_Detect,
825 .release = Pci2000_Release,
826 .queuecommand = Pci2000_QueueCommand,
827 .abort = Pci2000_Abort,
828 .reset = Pci2000_Reset,
829 .bios_param = Pci2000_BiosParam,
830 .can_queue = 16,
831 .this_id = -1,
832 .sg_tablesize = 16,
833 .cmd_per_lun = 1,
834 .use_clustering = DISABLE_CLUSTERING,
835};
836#include "scsi_module.c"