patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / scsi / pci2000.c
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 "hosts.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
72 typedef struct
73         {
74         unsigned int    address;
75         unsigned int    length;
76         }       SCATGATH, *PSCATGATH;
77
78 typedef 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
88 typedef 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
107 static struct   Scsi_Host          *PsiHost[MAXADAPTER] = {NULL,};  // One for each adapter
108 static                  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  ****************************************************************/
119 static 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  ****************************************************************/
141 static 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  ****************************************************************/
164 static 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  ****************************************************************/
180 static 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  ****************************************************************/
203 static 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, scsi_to_pci_dma_dir (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, SCpnt->request_buffer, SCpnt->request_bufflen, scsi_to_pci_dma_dir (SCpnt->sc_data_direction));
229         outl (SCpnt->SCp.have_data_in, padapter->mb2);
230         outl (SCpnt->request_bufflen, padapter->mb3);
231         return TRUE;
232         }
233 /*********************************************************************
234  *      Name:   PsiRaidCmd
235  *
236  *      Description:    Execute a simple command.
237  *
238  *      Parameters:             padapter - Pointer to adapter control structure.
239  *                                      cmd              - Roy command byte.
240  *
241  *      Returns:                Return error status.
242  *
243  ********************************************************************/
244 static int PsiRaidCmd (PADAPTER2000 padapter, char cmd)
245         {
246         if ( WaitReady (padapter) )                                             // test for command register ready
247                 return DID_TIME_OUT;
248         outb_p (cmd, padapter->cmd);                                    // issue command
249         if ( WaitReadyLong (padapter) )                                 // wait for adapter ready
250                 return DID_TIME_OUT;
251         return DID_OK;
252         }
253 /****************************************************************
254  *      Name:   Irq_Handler     :LOCAL
255  *
256  *      Description:    Interrupt handler.
257  *
258  *      Parameters:             irq             - Hardware IRQ number.
259  *                                      dev_id  -
260  *                                      regs    -
261  *
262  *      Returns:                TRUE if drive is not ready in time.
263  *
264  ****************************************************************/
265 static irqreturn_t Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
266         {
267         struct Scsi_Host   *shost = NULL;       // Pointer to host data block
268         PADAPTER2000            padapter;               // Pointer to adapter control structure
269         PDEV2000                        pdev;
270         Scsi_Cmnd                  *SCpnt;
271         UCHAR                           tag = 0;
272         UCHAR                           tag0;
273         ULONG                           error;
274         int                                     pun;
275         int                                     bus;
276         int                                     z;
277     unsigned long               flags;
278     int handled = 0;
279
280         DEB(printk ("\npci2000 received interrupt "));
281         for ( z = 0; z < NumAdapters;  z++ )                                                                            // scan for interrupt to process
282                 {
283                 if ( PsiHost[z]->irq == (UCHAR)(irq & 0xFF) )
284                         {
285                         tag = inb_p (HOSTDATA(PsiHost[z])->tag);
286                         if (  tag )
287                                 {
288                                 shost = PsiHost[z];
289                                 break;
290                                 }
291                         }
292                 }
293
294         if ( !shost )
295                 {
296                 DEB (printk ("\npci2000: not my interrupt"));
297                 goto out;
298                 }
299
300     handled = 1;
301         spin_lock_irqsave(shost->host_lock, flags);
302         padapter = HOSTDATA(shost);
303
304         tag0 = tag & 0x7F;                                                                                                                      // mask off the error bit
305         for ( bus = 0;  bus < MAX_BUS;  bus++ )                                                                         // scan the busses
306         {
307                 for ( pun = 0;  pun < MAX_UNITS;  pun++ )                                                               // scan the targets
308                 {
309                         pdev = &padapter->dev[bus][pun];
310                         if ( !pdev->tag )
311                         continue;
312                         if ( pdev->tag == tag0 )                                                                                        // is this it?
313                                 {
314                                 pdev->tag = 0;
315                                 SCpnt = pdev->SCpnt;
316                                 goto unmapProceed;
317                         }
318                         }
319         }
320
321         outb_p (0xFF, padapter->tag);                                                                                           // clear the op interrupt
322         outb_p (CMD_DONE, padapter->cmd);                                                                                       // complete the op
323         goto irq_return;                                                                                                                        // done, but, with what?
324
325 unmapProceed:;
326         if ( !bus )
327                 {
328                 switch ( SCpnt->cmnd[0] )
329                         {
330                         case SCSIOP_TEST_UNIT_READY:
331                                 pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, sizeof (SCpnt->sense_buffer), PCI_DMA_FROMDEVICE);
332                                 goto irqProceed;
333                         case SCSIOP_READ_CAPACITY:
334                                 pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, 8, PCI_DMA_FROMDEVICE);
335                                 goto irqProceed;
336                         case SCSIOP_VERIFY:
337                         case SCSIOP_START_STOP_UNIT:
338                         case SCSIOP_MEDIUM_REMOVAL:
339                                 goto irqProceed;
340                         }
341                 }
342         if ( SCpnt->SCp.have_data_in )
343                 pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, SCpnt->request_bufflen, scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
344         else 
345                 {
346                 if ( SCpnt->use_sg )
347                         pci_unmap_sg (padapter->pdev, (struct scatterlist *)SCpnt->request_buffer, SCpnt->use_sg, scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
348                 }
349
350 irqProceed:;
351         if ( tag & ERR08_TAGGED )                                                                                               // is there an error here?
352                 {
353                 if ( WaitReady (padapter) )
354                         {
355                         OpDone (SCpnt, DID_TIME_OUT << 16);
356                         goto irq_return;
357                         }
358
359                 outb_p (tag0, padapter->mb0);                                                                           // get real error code
360                 outb_p (CMD_ERROR, padapter->cmd);
361                 if ( WaitReady (padapter) )                                                                                     // wait for controller to suck up the op
362                         {
363                         OpDone (SCpnt, DID_TIME_OUT << 16);
364                         goto irq_return;
365                         }
366
367                 error = inl (padapter->mb0);                                                                            // get error data
368                 outb_p (0xFF, padapter->tag);                                                                           // clear the op interrupt
369                 outb_p (CMD_DONE, padapter->cmd);                                                                       // complete the op
370
371                 DEB (printk ("status: %lX ", error));
372                 if ( error == 0x00020002 )                                                                                      // is this error a check condition?
373                         {
374                         if ( bus )                                                                                                              // are we doint SCSI commands?
375                                 {
376                                 OpDone (SCpnt, (DID_OK << 16) | 2);
377                                 goto irq_return;
378                                 }
379                         if ( *SCpnt->cmnd == SCSIOP_TEST_UNIT_READY )
380                                 OpDone (SCpnt, (DRIVER_SENSE << 24) | (DID_OK << 16) | 2);      // test caller we have sense data too
381                         else
382                                 OpDone (SCpnt, DID_ERROR << 16);
383                         goto irq_return;
384                         }
385                 OpDone (SCpnt, DID_ERROR << 16);
386                 goto irq_return;
387                 }
388
389         outb_p (0xFF, padapter->tag);                                                                                   // clear the op interrupt
390         outb_p (CMD_DONE, padapter->cmd);                                                                               // complete the op
391         OpDone (SCpnt, DID_OK << 16);
392
393 irq_return:
394     spin_unlock_irqrestore(shost->host_lock, flags);
395 out:
396     return IRQ_RETVAL(handled);
397 }
398 /****************************************************************
399  *      Name:   Pci2000_QueueCommand
400  *
401  *      Description:    Process a queued command from the SCSI manager.
402  *
403  *      Parameters:             SCpnt - Pointer to SCSI command structure.
404  *                                      done  - Pointer to done function to call.
405  *
406  *      Returns:                Status code.
407  *
408  ****************************************************************/
409 int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
410         {
411         UCHAR              *cdb = (UCHAR *)SCpnt->cmnd;                                 // Pointer to SCSI CDB
412         PADAPTER2000    padapter = HOSTDATA(SCpnt->device->host);                       // Pointer to adapter control structure
413         int                             rc               = -1;                                                          // command return code
414         UCHAR                   bus              = SCpnt->device->channel;
415         UCHAR                   pun              = SCpnt->device->id;
416         UCHAR                   lun              = SCpnt->device->lun;
417         UCHAR                   cmd;
418         PDEV2000                pdev     = &padapter->dev[bus][pun];
419
420         if ( !done )
421                 {
422                 printk("pci2000_queuecommand: %02X: done can't be NULL\n", *cdb);
423                 return 0;
424                 }
425
426         SCpnt->scsi_done = done;
427         SCpnt->SCp.have_data_in = 0;
428         pdev->SCpnt = SCpnt;                                                                    // Save this command data
429
430         if ( WaitReady (padapter) )
431                 {
432                 rc = DID_ERROR;
433                 goto finished;
434                 }
435
436         outw_p (pun | (lun << 8), padapter->mb0);
437
438         if ( bus )
439                 {
440                 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]));
441                 DEB (if(*cdb) printk ("\ntimeout_per_command: %d, timeout_total: %d, timeout: %d, internal_timout: %d", SCpnt->timeout_per_command,
442                                                           SCpnt->timeout_total, SCpnt->timeout, SCpnt->internal_timeout));
443                 outl (SCpnt->timeout_per_command, padapter->mb1);
444                 outb_p (CMD_SCSI_TIMEOUT, padapter->cmd);
445                 if ( WaitReady (padapter) )
446                         {
447                         rc = DID_ERROR;
448                         goto finished;
449                         }
450
451                 outw_p (pun | (lun << 8), padapter->mb0);
452                 outw_p (SCpnt->cmd_len << 8, padapter->mb0 + 2);
453                 memcpy (pdev->cdb, cdb, MAX_COMMAND_SIZE);
454
455                 outl (pdev->cdbDma, padapter->mb1);
456                 if ( BuildSgList (SCpnt, padapter, pdev) )
457                         cmd = CMD_SCSI_THRU;
458                 else
459                         cmd = CMD_SCSI_THRU_SG;
460                 if ( (pdev->tag = Command (padapter, cmd)) == 0 )
461                         rc = DID_TIME_OUT;
462                 goto finished;
463                 }
464         else
465                 {
466                 if ( lun )
467                         {
468                         rc = DID_BAD_TARGET;
469                         goto finished;
470                         }
471                 }
472
473         switch ( *cdb )
474                 {
475                 case SCSIOP_INQUIRY:                                    // inquiry CDB
476                         if ( cdb[2] == SC_MY_RAID )
477                                 {
478                                 switch ( cdb[3] ) 
479                                         {
480                                         case MY_SCSI_REBUILD:
481                                                 OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_REBUILD) << 16);
482                                                 return 0;
483                                         case MY_SCSI_ALARMMUTE:
484                                                 OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_MUTE) << 16);
485                                                 return 0;
486                                         case MY_SCSI_DEMOFAIL:
487                                                 OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_FAIL) << 16);
488                                                 return 0;
489                                         default:
490                                                 if ( SCpnt->use_sg )
491                                                         {
492                                                         rc = DID_ERROR;
493                                                         goto finished;
494                                                         }
495                                                 else
496                                                         {
497                                                         SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, SCpnt->request_bufflen,
498                                                                                                           scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
499                                                         outl (SCpnt->SCp.have_data_in, padapter->mb2);
500                                                         }
501                                                 outl (cdb[5], padapter->mb0);
502                                                 outl (cdb[3], padapter->mb3);
503                                                 cmd = CMD_DASD_RAID_RQ;
504                                                 break;
505                                         }
506                                 break;
507                                 }
508                         
509                         if ( SCpnt->use_sg )
510                                 {
511                                 SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev,
512                                                                           ((struct scatterlist *)SCpnt->request_buffer)->address,
513                                                                           SCpnt->request_bufflen,
514                                                                           scsi_to_pci_dma_dir (SCpnt->sc_data_direction));
515                                 }
516                         else
517                                 {
518                                 SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer,
519                                                                           SCpnt->request_bufflen,
520                                                                           scsi_to_pci_dma_dir (SCpnt->sc_data_direction));
521                                 }
522                         outl (SCpnt->SCp.have_data_in, padapter->mb2);
523                         outl (SCpnt->request_bufflen, padapter->mb3);
524                         cmd = CMD_DASD_SCSI_INQ;
525                         break;
526
527                 case SCSIOP_TEST_UNIT_READY:                    // test unit ready CDB
528                         SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->sense_buffer, sizeof (SCpnt->sense_buffer), PCI_DMA_FROMDEVICE);
529                         outl (SCpnt->SCp.have_data_in, padapter->mb2);
530                         outl (sizeof (SCpnt->sense_buffer), padapter->mb3);
531                         cmd = CMD_TEST_READY;
532                         break;
533
534                 case SCSIOP_READ_CAPACITY:                              // read capacity CDB
535                         if ( SCpnt->use_sg )
536                                 {
537                                 SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, ((struct scatterlist *)(SCpnt->request_buffer))->address,
538                                                                                   8, PCI_DMA_FROMDEVICE);
539                                 }
540                         else
541                                 SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, 8, PCI_DMA_FROMDEVICE);
542                         outl (SCpnt->SCp.have_data_in, padapter->mb2);
543                         outl (8, padapter->mb3);
544                         cmd = CMD_DASD_CAP;
545                         break;
546                 case SCSIOP_VERIFY:                                             // verify CDB
547                         outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
548                         outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
549                         cmd = CMD_READ_SG;
550                         break;
551                 case SCSIOP_READ:                                               // read10 CDB
552                         outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
553                         outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
554                         if ( BuildSgList (SCpnt, padapter, pdev) )
555                                 cmd = CMD_READ;
556                         else
557                                 cmd = CMD_READ_SG;
558                         break;
559                 case SCSIOP_READ6:                                              // read6  CDB
560                         outw_p (cdb[4], padapter->mb0 + 2);
561                         outl ((SCSI2LONG (&cdb[1])) & 0x001FFFFF, padapter->mb1);
562                         if ( BuildSgList (SCpnt, padapter, pdev) )
563                                 cmd = CMD_READ;
564                         else
565                                 cmd = CMD_READ_SG;
566                         break;
567                 case SCSIOP_WRITE:                                              // write10 CDB
568                         outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
569                         outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
570                         if ( BuildSgList (SCpnt, padapter, pdev) )
571                                 cmd = CMD_WRITE;
572                         else
573                                 cmd = CMD_WRITE_SG;
574                         break;
575                 case SCSIOP_WRITE6:                                             // write6  CDB
576                         outw_p (cdb[4], padapter->mb0 + 2);
577                         outl ((SCSI2LONG (&cdb[1])) & 0x001FFFFF, padapter->mb1);
578                         if ( BuildSgList (SCpnt, padapter, pdev) )
579                                 cmd = CMD_WRITE;
580                         else
581                                 cmd = CMD_WRITE_SG;
582                         break;
583                 case SCSIOP_START_STOP_UNIT:
584                         cmd = CMD_EJECT_MEDIA;
585                         break;
586                 case SCSIOP_MEDIUM_REMOVAL:
587                         switch ( cdb[4] )
588                                 {
589                                 case 0:
590                                         cmd = CMD_UNLOCK_DOOR;
591                                         break;
592                                 case 1:
593                                         cmd = CMD_LOCK_DOOR;
594                                         break;
595                                 default:
596                                         cmd = 0;
597                                         break;
598                                 }
599                         if ( cmd )
600                                 break;
601                 default:
602                         DEB (printk ("pci2000_queuecommand: Unsupported command %02X\n", *cdb));
603                         OpDone (SCpnt, DID_ERROR << 16);
604                         return 0;
605                 }
606
607         if ( (pdev->tag = Command (padapter, cmd)) == 0 )
608                 rc = DID_TIME_OUT;
609 finished:;
610         if ( rc != -1 )
611                 OpDone (SCpnt, rc << 16);
612         return 0;
613         }
614 /****************************************************************
615  *      Name:   Pci2000_Detect
616  *
617  *      Description:    Detect and initialize our boards.
618  *
619  *      Parameters:             tpnt - Pointer to SCSI host template structure.
620  *
621  *      Returns:                Number of adapters installed.
622  *
623  ****************************************************************/
624 int Pci2000_Detect (Scsi_Host_Template *tpnt)
625         {
626         int                                     found = 0;
627         int                                     installed = 0;
628         struct Scsi_Host   *pshost;
629         PADAPTER2000        padapter;
630         int                                     z, zz;
631         int                                     setirq;
632         struct pci_dev     *pdev = NULL;
633         UCHAR                      *consistent;
634         dma_addr_t                      consistentDma;
635
636         while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_ROY_1, pdev)) != NULL )
637                 {
638                 if (pci_enable_device(pdev))
639                         continue;
640                 pshost = scsi_register (tpnt, sizeof(ADAPTER2000));
641                 if(pshost == NULL)
642                         continue;
643                 padapter = HOSTDATA(pshost);
644
645                 padapter->basePort = pci_resource_start (pdev, 1);
646                 DEB (printk ("\nBase Regs = %#04X", padapter->basePort));                       // get the base I/O port address
647                 padapter->mb0   = padapter->basePort + RTR_MAILBOX;                                     // get the 32 bit mail boxes
648                 padapter->mb1   = padapter->basePort + RTR_MAILBOX + 4;
649                 padapter->mb2   = padapter->basePort + RTR_MAILBOX + 8;
650                 padapter->mb3   = padapter->basePort + RTR_MAILBOX + 12;
651                 padapter->mb4   = padapter->basePort + RTR_MAILBOX + 16;
652                 padapter->cmd   = padapter->basePort + RTR_LOCAL_DOORBELL;                      // command register
653                 padapter->tag   = padapter->basePort + RTR_PCI_DOORBELL;                        // tag/response register
654                 padapter->pdev = pdev;
655
656                 if ( WaitReady (padapter) )
657                         goto unregister;
658                 outb_p (0x84, padapter->mb0);
659                 outb_p (CMD_SPECIFY, padapter->cmd);
660                 if ( WaitReady (padapter) )
661                         goto unregister;
662
663                 consistent = pci_alloc_consistent (pdev, consistentLen, &consistentDma);
664                 if ( !consistent )
665                         {
666                         printk ("Unable to allocate DMA memory for PCI-2000 controller.\n");
667                         goto unregister;
668                         }
669                 
670                 scsi_set_device(pshost, &pdev->dev);
671                 pshost->irq = pdev->irq;
672                 setirq = 1;
673                 padapter->irqOwned = 0;
674                 for ( z = 0;  z < installed;  z++ )                                                                     // scan for shared interrupts
675                         {
676                         if ( PsiHost[z]->irq == pshost->irq )                                                   // if shared then, don't posses
677                                 setirq = 0;
678                         }
679                 if ( setirq )                                                                                           // if not shared, posses
680                         {
681                         if ( request_irq (pshost->irq, Irq_Handler, SA_SHIRQ, "pci2000", padapter) < 0 )
682                                 {
683                                 if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2000", padapter) < 0 )
684                                         {
685                                         printk ("Unable to allocate IRQ for PCI-2000 controller.\n");
686                                         pci_free_consistent (pdev, consistentLen, consistent, consistentDma);
687                                         goto unregister;
688                                         }
689                                 }
690                         padapter->irqOwned = pshost->irq;                                               // set IRQ as owned
691                         }
692                 PsiHost[installed]      = pshost;                                                                               // save SCSI_HOST pointer
693
694                 pshost->io_port         = padapter->basePort;
695                 pshost->n_io_port       = 0xFF;
696                 pshost->unique_id       = padapter->basePort;
697                 pshost->max_id          = 16;
698                 pshost->max_channel     = 1;
699
700                 for ( zz = 0;  zz < MAX_BUS;  zz++ )
701                         for ( z = 0; z < MAX_UNITS;  z++ )
702                                 {
703                                 padapter->dev[zz][z].tag = 0;
704                                 padapter->dev[zz][z].scatGath = (PSCATGATH)consistent;
705                                 padapter->dev[zz][z].scatGathDma = consistentDma;
706                                 consistent += 16 * sizeof (SCATGATH);
707                                 consistentDma += 16 * sizeof (SCATGATH);
708                                 padapter->dev[zz][z].cdb = (UCHAR *)consistent;
709                                 padapter->dev[zz][z].cdbDma = consistentDma;
710                                 consistent += MAX_COMMAND_SIZE;
711                                 consistentDma += MAX_COMMAND_SIZE;
712                                 }
713                         
714                 printk("\nPSI-2000 Intelligent Storage SCSI CONTROLLER: at I/O = %lX  IRQ = %d\n", padapter->basePort, pshost->irq);
715                 printk("Version %s, Compiled %s %s\n\n", PCI2000_VERSION,  __DATE__, __TIME__);
716                 found++;
717                 if ( ++installed < MAXADAPTER )
718                         continue;
719                 break;
720 unregister:;
721                 scsi_unregister (pshost);
722                 found++;
723                 }
724         NumAdapters = installed;
725         return installed;
726         }
727 /****************************************************************
728  *      Name:   Pci2000_Abort
729  *
730  *      Description:    Process the Abort command from the SCSI manager.
731  *
732  *      Parameters:             SCpnt - Pointer to SCSI command structure.
733  *
734  *      Returns:                Allways snooze.
735  *
736  ****************************************************************/
737 int Pci2000_Abort (Scsi_Cmnd *SCpnt)
738         {
739         DEB (printk ("pci2000_abort\n"));
740         return SCSI_ABORT_SNOOZE;
741         }
742 /****************************************************************
743  *      Name:   Pci2000_Reset
744  *
745  *      Description:    Process the Reset command from the SCSI manager.
746  *
747  *      Parameters:             SCpnt - Pointer to SCSI command structure.
748  *                                      flags - Flags about the reset command
749  *
750  *      Returns:                No active command at this time, so this means
751  *                                      that each time we got some kind of response the
752  *                                      last time through.  Tell the mid-level code to
753  *                                      request sense information in order to decide what
754  *                                      to do next.
755  *
756  ****************************************************************/
757 int Pci2000_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
758         {
759         return SCSI_RESET_PUNT;
760         }
761 /****************************************************************
762  *      Name:   Pci2000_Release
763  *
764  *      Description:    Release resources allocated for a single each adapter.
765  *
766  *      Parameters:             pshost - Pointer to SCSI command structure.
767  *
768  *      Returns:                zero.
769  *
770  ****************************************************************/
771 int Pci2000_Release (struct Scsi_Host *pshost)
772         {
773     PADAPTER2000        padapter = HOSTDATA (pshost);
774
775         if ( padapter->irqOwned )
776                 free_irq (pshost->irq, padapter);
777         pci_free_consistent (padapter->pdev, consistentLen, padapter->dev[0][0].scatGath, padapter->dev[0][0].scatGathDma);
778         release_region (pshost->io_port, pshost->n_io_port);
779     scsi_unregister(pshost);
780     return 0;
781         }
782
783 /****************************************************************
784  *      Name:   Pci2000_BiosParam
785  *
786  *      Description:    Process the biosparam request from the SCSI manager to
787  *                                      return C/H/S data.
788  *
789  *      Parameters:             disk - Pointer to SCSI disk structure.
790  *                                      dev      - Major/minor number from kernel.
791  *                                      geom - Pointer to integer array to place geometry data.
792  *
793  *      Returns:                zero.
794  *
795  ****************************************************************/
796 int Pci2000_BiosParam (struct scsi_device *sdev, struct block_device *dev,
797                 sector_t capacity, int geom[])
798         {
799         PADAPTER2000        padapter;
800
801         padapter = HOSTDATA(sdev->host);
802
803         if ( WaitReady (padapter) )
804                 return 0;
805         outb_p (sdev->id, padapter->mb0);
806         outb_p (CMD_GET_PARMS, padapter->cmd);
807         if ( WaitReady (padapter) )
808                 return 0;
809
810         geom[0] = inb_p (padapter->mb2 + 3);
811         geom[1] = inb_p (padapter->mb2 + 2);
812         geom[2] = inw_p (padapter->mb2);
813         return 0;
814         }
815
816
817 MODULE_LICENSE("Dual BSD/GPL");
818
819 static Scsi_Host_Template driver_template = {
820         .proc_name      = "pci2000",
821         .name           = "PCI-2000 SCSI Intelligent Disk Controller",
822         .detect         = Pci2000_Detect,
823         .release        = Pci2000_Release,
824         .queuecommand   = Pci2000_QueueCommand,
825         .abort          = Pci2000_Abort,
826         .reset          = Pci2000_Reset,
827         .bios_param     = Pci2000_BiosParam,
828         .can_queue      = 16,
829         .this_id        = -1,
830         .sg_tablesize   = 16,
831         .cmd_per_lun    = 1,
832         .use_clustering = DISABLE_CLUSTERING,
833 };
834 #include "scsi_module.c"