vserver 2.0 rc7
[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 <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
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, 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  ********************************************************************/
246 static 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  ****************************************************************/
267 static 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
327 unmapProceed:;
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
352 irqProceed:;
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
395 irq_return:
396     spin_unlock_irqrestore(shost->host_lock, flags);
397 out:
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  ****************************************************************/
411 int 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;
611 finished:;
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  ****************************************************************/
626 int 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;
722 unregister:;
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  ****************************************************************/
739 int 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  ****************************************************************/
759 int 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  ****************************************************************/
773 int 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  ****************************************************************/
798 int 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
819 MODULE_LICENSE("Dual BSD/GPL");
820
821 static 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"