make oldconfig will rebuild these...
[linux-2.4.21-pre4.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/module.h>
39
40 #include <linux/kernel.h>
41 #include <linux/types.h>
42 #include <linux/string.h>
43 #include <linux/pci.h>
44 #include <linux/ioport.h>
45 #include <linux/delay.h>
46 #include <linux/sched.h>
47 #include <linux/proc_fs.h>
48 #include <asm/dma.h>
49 #include <asm/system.h>
50 #include <asm/io.h>
51 #include <linux/blk.h>
52 #include "scsi.h"
53 #include "hosts.h"
54 #include <linux/stat.h>
55 #include <linux/spinlock.h>
56
57 #include "pci2000.h"
58 #include "psi_roy.h"
59
60
61 //#define DEBUG 1
62
63 #ifdef DEBUG
64 #define DEB(x) x
65 #define STOP_HERE       {int st;for(st=0;st<100;st++){st=1;}}
66 #else
67 #define DEB(x)
68 #define STOP_HERE
69 #endif
70
71 typedef struct
72         {
73         unsigned int    address;
74         unsigned int    length;
75         }       SCATGATH, *PSCATGATH;
76
77 typedef struct
78         {
79         Scsi_Cmnd               *SCpnt;
80         PSCATGATH                scatGath;
81         dma_addr_t               scatGathDma;
82         UCHAR                   *cdb;
83         dma_addr_t               cdbDma; 
84         UCHAR                    tag;
85         }       DEV2000, *PDEV2000;
86
87 typedef struct
88         {
89         ULONG                    basePort;
90         ULONG                    mb0;
91         ULONG                    mb1;
92         ULONG                    mb2;
93         ULONG                    mb3;
94         ULONG                    mb4;
95         ULONG                    cmd;
96         ULONG                    tag;
97         ULONG                    irqOwned;
98         struct pci_dev  *pdev;
99         DEV2000                  dev[MAX_BUS][MAX_UNITS];
100         }       ADAPTER2000, *PADAPTER2000;
101
102 #define HOSTDATA(host) ((PADAPTER2000)&host->hostdata)
103 #define consistentLen (MAX_BUS * MAX_UNITS * (16 * sizeof (SCATGATH) + MAX_COMMAND_SIZE))
104
105
106 static struct   Scsi_Host          *PsiHost[MAXADAPTER] = {NULL,};  // One for each adapter
107 static                  int                             NumAdapters = 0;
108 /****************************************************************
109  *      Name:                   WaitReady       :LOCAL
110  *
111  *      Description:    Wait for controller ready.
112  *
113  *      Parameters:             padapter - Pointer adapter data structure.
114  *
115  *      Returns:                TRUE on not ready.
116  *
117  ****************************************************************/
118 static int WaitReady (PADAPTER2000 padapter)
119         {
120         ULONG   z;
121
122         for ( z = 0;  z < (TIMEOUT_COMMAND * 4);  z++ )
123                 {
124                 if ( !inb_p (padapter->cmd) )
125                         return FALSE;
126                 udelay (250);
127                 };                                                              
128         return TRUE;
129         }
130 /****************************************************************
131  *      Name:                   WaitReadyLong   :LOCAL
132  *
133  *      Description:    Wait for controller ready.
134  *
135  *      Parameters:             padapter - Pointer adapter data structure.
136  *
137  *      Returns:                TRUE on not ready.
138  *
139  ****************************************************************/
140 static int WaitReadyLong (PADAPTER2000 padapter)
141         {
142         ULONG   z;
143
144         for ( z = 0;  z < (5000 * 4);  z++ )
145                 {
146                 if ( !inb_p (padapter->cmd) )
147                         return FALSE;
148                 udelay (250);
149                 };                                                              
150         return TRUE;
151         }
152 /****************************************************************
153  *      Name:   OpDone  :LOCAL
154  *
155  *      Description:    Clean up operation and issue done to caller.
156  *
157  *      Parameters:             SCpnt   - Pointer to SCSI command structure.
158  *                                      status  - Caller status.
159  *
160  *      Returns:                Nothing.
161  *
162  ****************************************************************/
163 static void OpDone (Scsi_Cmnd *SCpnt, ULONG status)
164         {
165         SCpnt->result = status;
166         SCpnt->scsi_done (SCpnt);
167         }
168 /****************************************************************
169  *      Name:   Command         :LOCAL
170  *
171  *      Description:    Issue queued command to the PCI-2000.
172  *
173  *      Parameters:             padapter - Pointer to adapter information structure.
174  *                                      cmd              - PCI-2000 command byte.
175  *
176  *      Returns:                Non-zero command tag if operation is accepted.
177  *
178  ****************************************************************/
179 static UCHAR Command (PADAPTER2000 padapter, UCHAR cmd)
180         {
181         outb_p (cmd, padapter->cmd);
182         if ( WaitReady (padapter) )
183                 return 0;
184
185         if ( inw_p (padapter->mb0) )
186                 return 0;
187
188         return inb_p (padapter->mb1);
189         }
190 /****************************************************************
191  *      Name:   BuildSgList             :LOCAL
192  *
193  *      Description:    Build the scatter gather list for controller.
194  *
195  *      Parameters:             SCpnt    - Pointer to SCSI command structure.
196  *                                      padapter - Pointer to adapter information structure.
197  *                                      pdev     - Pointer to adapter device structure.
198  *
199  *      Returns:                Non-zero in not scatter gather.
200  *
201  ****************************************************************/
202 static int BuildSgList (Scsi_Cmnd *SCpnt, PADAPTER2000 padapter, PDEV2000 pdev)
203         {
204         int                                      z;
205         int                                      zc;
206         struct scatterlist      *sg;
207
208         if ( SCpnt->use_sg )
209                 {
210                 sg = (struct scatterlist *)SCpnt->request_buffer;
211                 zc = pci_map_sg (padapter->pdev, sg, SCpnt->use_sg, scsi_to_pci_dma_dir (SCpnt->sc_data_direction));
212                 for ( z = 0;  z < zc;  z++ )
213                         {
214                         pdev->scatGath[z].address = cpu_to_le32 (sg_dma_address (sg));
215                         pdev->scatGath[z].length = cpu_to_le32 (sg_dma_len (sg++));
216                         }
217                 outl (pdev->scatGathDma, padapter->mb2);
218                 outl ((zc << 24) | SCpnt->request_bufflen, padapter->mb3);
219                 return FALSE;
220                 }
221         if ( !SCpnt->request_bufflen)
222                 {
223                 outl (0, padapter->mb2);
224                 outl (0, padapter->mb3);
225                 return TRUE;
226                 }
227         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));
228         outl (SCpnt->SCp.have_data_in, padapter->mb2);
229         outl (SCpnt->request_bufflen, padapter->mb3);
230         return TRUE;
231         }
232 /*********************************************************************
233  *      Name:   PsiRaidCmd
234  *
235  *      Description:    Execute a simple command.
236  *
237  *      Parameters:             padapter - Pointer to adapter control structure.
238  *                                      cmd              - Roy command byte.
239  *
240  *      Returns:                Return error status.
241  *
242  ********************************************************************/
243 static int PsiRaidCmd (PADAPTER2000 padapter, char cmd)
244         {
245         if ( WaitReady (padapter) )                                             // test for command register ready
246                 return DID_TIME_OUT;
247         outb_p (cmd, padapter->cmd);                                    // issue command
248         if ( WaitReadyLong (padapter) )                                 // wait for adapter ready
249                 return DID_TIME_OUT;
250         return DID_OK;
251         }
252 /****************************************************************
253  *      Name:   Irq_Handler     :LOCAL
254  *
255  *      Description:    Interrupt handler.
256  *
257  *      Parameters:             irq             - Hardware IRQ number.
258  *                                      dev_id  -
259  *                                      regs    -
260  *
261  *      Returns:                TRUE if drive is not ready in time.
262  *
263  ****************************************************************/
264 static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
265         {
266         struct Scsi_Host   *shost = NULL;       // Pointer to host data block
267         PADAPTER2000            padapter;               // Pointer to adapter control structure
268         PDEV2000                        pdev;
269         Scsi_Cmnd                  *SCpnt;
270         UCHAR                           tag = 0;
271         UCHAR                           tag0;
272         ULONG                           error;
273         int                                     pun;
274         int                                     bus;
275         int                                     z;
276     unsigned long               flags;
277
278     /*
279      * Disable interrupts, if they aren't already disabled and acquire
280      * the I/O spinlock.
281      */
282     spin_lock_irqsave (&io_request_lock, flags);
283
284         DEB(printk ("\npci2000 received interrupt "));
285         for ( z = 0; z < NumAdapters;  z++ )                                                                            // scan for interrupt to process
286                 {
287                 if ( PsiHost[z]->irq == (UCHAR)(irq & 0xFF) )
288                         {
289                         tag = inb_p (HOSTDATA(PsiHost[z])->tag);
290                         if (  tag )
291                                 {
292                                 shost = PsiHost[z];
293                                 break;
294                                 }
295                         }
296                 }
297
298         if ( !shost )
299                 {
300                 DEB (printk ("\npci2000: not my interrupt"));
301                 goto irq_return;
302                 }
303
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, scsi_to_pci_dma_dir(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, scsi_to_pci_dma_dir(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     /*
397      * Release the I/O spinlock and restore the original flags
398      * which will enable interrupts if and only if they were
399      * enabled on entry.
400      */
401     spin_unlock_irqrestore (&io_request_lock, flags);
402         }
403 /****************************************************************
404  *      Name:   Pci2000_QueueCommand
405  *
406  *      Description:    Process a queued command from the SCSI manager.
407  *
408  *      Parameters:             SCpnt - Pointer to SCSI command structure.
409  *                                      done  - Pointer to done function to call.
410  *
411  *      Returns:                Status code.
412  *
413  ****************************************************************/
414 int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
415         {
416         UCHAR              *cdb = (UCHAR *)SCpnt->cmnd;                                 // Pointer to SCSI CDB
417         PADAPTER2000    padapter = HOSTDATA(SCpnt->host);                       // Pointer to adapter control structure
418         int                             rc               = -1;                                                          // command return code
419         UCHAR                   bus              = SCpnt->channel;
420         UCHAR                   pun              = SCpnt->target;
421         UCHAR                   lun              = SCpnt->lun;
422         UCHAR                   cmd;
423         PDEV2000                pdev     = &padapter->dev[bus][pun];
424
425         if ( !done )
426                 {
427                 printk("pci2000_queuecommand: %02X: done can't be NULL\n", *cdb);
428                 return 0;
429                 }
430
431         SCpnt->scsi_done = done;
432         SCpnt->SCp.have_data_in = 0;
433         pdev->SCpnt = SCpnt;                                                                    // Save this command data
434
435         if ( WaitReady (padapter) )
436                 {
437                 rc = DID_ERROR;
438                 goto finished;
439                 }
440
441         outw_p (pun | (lun << 8), padapter->mb0);
442
443         if ( bus )
444                 {
445                 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]));
446                 DEB (if(*cdb) printk ("\ntimeout_per_command: %d, timeout_total: %d, timeout: %d, internal_timout: %d", SCpnt->timeout_per_command,
447                                                           SCpnt->timeout_total, SCpnt->timeout, SCpnt->internal_timeout));
448                 outl (SCpnt->timeout_per_command, padapter->mb1);
449                 outb_p (CMD_SCSI_TIMEOUT, padapter->cmd);
450                 if ( WaitReady (padapter) )
451                         {
452                         rc = DID_ERROR;
453                         goto finished;
454                         }
455
456                 outw_p (pun | (lun << 8), padapter->mb0);
457                 outw_p (SCpnt->cmd_len << 8, padapter->mb0 + 2);
458                 memcpy (pdev->cdb, cdb, MAX_COMMAND_SIZE);
459
460                 outl (pdev->cdbDma, padapter->mb1);
461                 if ( BuildSgList (SCpnt, padapter, pdev) )
462                         cmd = CMD_SCSI_THRU;
463                 else
464                         cmd = CMD_SCSI_THRU_SG;
465                 if ( (pdev->tag = Command (padapter, cmd)) == 0 )
466                         rc = DID_TIME_OUT;
467                 goto finished;
468                 }
469         else
470                 {
471                 if ( lun )
472                         {
473                         rc = DID_BAD_TARGET;
474                         goto finished;
475                         }
476                 }
477
478         switch ( *cdb )
479                 {
480                 case SCSIOP_INQUIRY:                                    // inquiry CDB
481                         if ( cdb[2] == SC_MY_RAID )
482                                 {
483                                 switch ( cdb[3] ) 
484                                         {
485                                         case MY_SCSI_REBUILD:
486                                                 OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_REBUILD) << 16);
487                                                 return 0;
488                                         case MY_SCSI_ALARMMUTE:
489                                                 OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_MUTE) << 16);
490                                                 return 0;
491                                         case MY_SCSI_DEMOFAIL:
492                                                 OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_FAIL) << 16);
493                                                 return 0;
494                                         default:
495                                                 if ( SCpnt->use_sg )
496                                                         {
497                                                         rc = DID_ERROR;
498                                                         goto finished;
499                                                         }
500                                                 else
501                                                         {
502                                                         SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, SCpnt->request_bufflen,
503                                                                                                           scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
504                                                         outl (SCpnt->SCp.have_data_in, padapter->mb2);
505                                                         }
506                                                 outl (cdb[5], padapter->mb0);
507                                                 outl (cdb[3], padapter->mb3);
508                                                 cmd = CMD_DASD_RAID_RQ;
509                                                 break;
510                                         }
511                                 break;
512                                 }
513                         
514                         if ( SCpnt->use_sg )
515                                 {
516                                 SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, ((struct scatterlist *)SCpnt->request_buffer)->address, 
517                                                                                   SCpnt->request_bufflen, scsi_to_pci_dma_dir (SCpnt->sc_data_direction));
518                                 }
519                         else
520                                 {
521                                 SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, 
522                                                                                   SCpnt->request_bufflen, scsi_to_pci_dma_dir (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:   internal_done :LOCAL
618  *
619  *      Description:    Done handler for non-queued commands
620  *
621  *      Parameters:             SCpnt - Pointer to SCSI command structure.
622  *
623  *      Returns:                Nothing.
624  *
625  ****************************************************************/
626 static void internal_done (Scsi_Cmnd * SCpnt)
627         {
628         SCpnt->SCp.Status++;
629         }
630 /****************************************************************
631  *      Name:   Pci2000_Command
632  *
633  *      Description:    Process a command from the SCSI manager.
634  *
635  *      Parameters:             SCpnt - Pointer to SCSI command structure.
636  *
637  *      Returns:                Status code.
638  *
639  ****************************************************************/
640 int Pci2000_Command (Scsi_Cmnd *SCpnt)
641         {
642         DEB(printk("pci2000_command: ..calling pci2000_queuecommand\n"));
643
644         Pci2000_QueueCommand (SCpnt, internal_done);
645
646     SCpnt->SCp.Status = 0;
647         while (!SCpnt->SCp.Status)
648                 barrier ();
649         return SCpnt->result;
650         }
651 /****************************************************************
652  *      Name:   Pci2000_Detect
653  *
654  *      Description:    Detect and initialize our boards.
655  *
656  *      Parameters:             tpnt - Pointer to SCSI host template structure.
657  *
658  *      Returns:                Number of adapters installed.
659  *
660  ****************************************************************/
661 int Pci2000_Detect (Scsi_Host_Template *tpnt)
662         {
663         int                                     found = 0;
664         int                                     installed = 0;
665         struct Scsi_Host   *pshost;
666         PADAPTER2000        padapter;
667         int                                     z, zz;
668         int                                     setirq;
669         struct pci_dev     *pdev = NULL;
670         UCHAR                      *consistent;
671         dma_addr_t                      consistentDma;
672
673
674         if ( !pci_present () )
675                 {
676                 printk ("pci2000: PCI BIOS not present\n");
677                 return 0;
678                 }
679
680         while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_ROY_1, pdev)) != NULL )
681                 {
682                 if (pci_enable_device(pdev))
683                         continue;
684                 pshost = scsi_register (tpnt, sizeof(ADAPTER2000));
685                 if(pshost == NULL)
686                         continue;
687                 padapter = HOSTDATA(pshost);
688
689                 padapter->basePort = pci_resource_start (pdev, 1);
690                 DEB (printk ("\nBase Regs = %#04X", padapter->basePort));                       // get the base I/O port address
691                 padapter->mb0   = padapter->basePort + RTR_MAILBOX;                                     // get the 32 bit mail boxes
692                 padapter->mb1   = padapter->basePort + RTR_MAILBOX + 4;
693                 padapter->mb2   = padapter->basePort + RTR_MAILBOX + 8;
694                 padapter->mb3   = padapter->basePort + RTR_MAILBOX + 12;
695                 padapter->mb4   = padapter->basePort + RTR_MAILBOX + 16;
696                 padapter->cmd   = padapter->basePort + RTR_LOCAL_DOORBELL;                      // command register
697                 padapter->tag   = padapter->basePort + RTR_PCI_DOORBELL;                        // tag/response register
698                 padapter->pdev = pdev;
699
700                 if ( WaitReady (padapter) )
701                         goto unregister;
702                 outb_p (0x84, padapter->mb0);
703                 outb_p (CMD_SPECIFY, padapter->cmd);
704                 if ( WaitReady (padapter) )
705                         goto unregister;
706
707                 consistent = pci_alloc_consistent (pdev, consistentLen, &consistentDma);
708                 if ( !consistent )
709                         {
710                         printk ("Unable to allocate DMA memory for PCI-2000 controller.\n");
711                         goto unregister;
712                         }
713                 
714                 scsi_set_pci_device(pshost, pdev);
715                 pshost->irq = pdev->irq;
716                 setirq = 1;
717                 padapter->irqOwned = 0;
718                 for ( z = 0;  z < installed;  z++ )                                                                     // scan for shared interrupts
719                         {
720                         if ( PsiHost[z]->irq == pshost->irq )                                                   // if shared then, don't posses
721                                 setirq = 0;
722                         }
723                 if ( setirq )                                                                                           // if not shared, posses
724                         {
725                         if ( request_irq (pshost->irq, Irq_Handler, SA_SHIRQ, "pci2000", padapter) < 0 )
726                                 {
727                                 if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2000", padapter) < 0 )
728                                         {
729                                         printk ("Unable to allocate IRQ for PCI-2000 controller.\n");
730                                         pci_free_consistent (pdev, consistentLen, consistent, consistentDma);
731                                         goto unregister;
732                                         }
733                                 }
734                         padapter->irqOwned = pshost->irq;                                               // set IRQ as owned
735                         }
736                 PsiHost[installed]      = pshost;                                                                               // save SCSI_HOST pointer
737
738                 pshost->io_port         = padapter->basePort;
739                 pshost->n_io_port       = 0xFF;
740                 pshost->unique_id       = padapter->basePort;
741                 pshost->max_id          = 16;
742                 pshost->max_channel     = 1;
743
744                 for ( zz = 0;  zz < MAX_BUS;  zz++ )
745                         for ( z = 0; z < MAX_UNITS;  z++ )
746                                 {
747                                 padapter->dev[zz][z].tag = 0;
748                                 padapter->dev[zz][z].scatGath = (PSCATGATH)consistent;
749                                 padapter->dev[zz][z].scatGathDma = consistentDma;
750                                 consistent += 16 * sizeof (SCATGATH);
751                                 consistentDma += 16 * sizeof (SCATGATH);
752                                 padapter->dev[zz][z].cdb = (UCHAR *)consistent;
753                                 padapter->dev[zz][z].cdbDma = consistentDma;
754                                 consistent += MAX_COMMAND_SIZE;
755                                 consistentDma += MAX_COMMAND_SIZE;
756                                 }
757                         
758                 printk("\nPSI-2000 Intelligent Storage SCSI CONTROLLER: at I/O = %lX  IRQ = %d\n", padapter->basePort, pshost->irq);
759                 printk("Version %s, Compiled %s %s\n\n", PCI2000_VERSION,  __DATE__, __TIME__);
760                 found++;
761                 if ( ++installed < MAXADAPTER )
762                         continue;
763                 break;
764 unregister:;
765                 scsi_unregister (pshost);
766                 found++;
767                 }
768         NumAdapters = installed;
769         return installed;
770         }
771 /****************************************************************
772  *      Name:   Pci2000_Abort
773  *
774  *      Description:    Process the Abort command from the SCSI manager.
775  *
776  *      Parameters:             SCpnt - Pointer to SCSI command structure.
777  *
778  *      Returns:                Allways snooze.
779  *
780  ****************************************************************/
781 int Pci2000_Abort (Scsi_Cmnd *SCpnt)
782         {
783         DEB (printk ("pci2000_abort\n"));
784         return SCSI_ABORT_SNOOZE;
785         }
786 /****************************************************************
787  *      Name:   Pci2000_Reset
788  *
789  *      Description:    Process the Reset command from the SCSI manager.
790  *
791  *      Parameters:             SCpnt - Pointer to SCSI command structure.
792  *                                      flags - Flags about the reset command
793  *
794  *      Returns:                No active command at this time, so this means
795  *                                      that each time we got some kind of response the
796  *                                      last time through.  Tell the mid-level code to
797  *                                      request sense information in order to decide what
798  *                                      to do next.
799  *
800  ****************************************************************/
801 int Pci2000_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
802         {
803         return SCSI_RESET_PUNT;
804         }
805 /****************************************************************
806  *      Name:   Pci2000_Release
807  *
808  *      Description:    Release resources allocated for a single each adapter.
809  *
810  *      Parameters:             pshost - Pointer to SCSI command structure.
811  *
812  *      Returns:                zero.
813  *
814  ****************************************************************/
815 int Pci2000_Release (struct Scsi_Host *pshost)
816         {
817     PADAPTER2000        padapter = HOSTDATA (pshost);
818
819         if ( padapter->irqOwned )
820                 free_irq (pshost->irq, padapter);
821         pci_free_consistent (padapter->pdev, consistentLen, padapter->dev[0][0].scatGath, padapter->dev[0][0].scatGathDma);
822         release_region (pshost->io_port, pshost->n_io_port);
823     scsi_unregister(pshost);
824     return 0;
825         }
826
827 #include "sd.h"
828 /****************************************************************
829  *      Name:   Pci2000_BiosParam
830  *
831  *      Description:    Process the biosparam request from the SCSI manager to
832  *                                      return C/H/S data.
833  *
834  *      Parameters:             disk - Pointer to SCSI disk structure.
835  *                                      dev      - Major/minor number from kernel.
836  *                                      geom - Pointer to integer array to place geometry data.
837  *
838  *      Returns:                zero.
839  *
840  ****************************************************************/
841 int Pci2000_BiosParam (Scsi_Disk *disk, kdev_t dev, int geom[])
842         {
843         PADAPTER2000        padapter;
844
845         padapter = HOSTDATA(disk->device->host);
846
847         if ( WaitReady (padapter) )
848                 return 0;
849         outb_p (disk->device->id, padapter->mb0);
850         outb_p (CMD_GET_PARMS, padapter->cmd);
851         if ( WaitReady (padapter) )
852                 return 0;
853
854         geom[0] = inb_p (padapter->mb2 + 3);
855         geom[1] = inb_p (padapter->mb2 + 2);
856         geom[2] = inw_p (padapter->mb2);
857         return 0;
858         }
859
860
861 MODULE_LICENSE("Dual BSD/GPL");
862 /* Eventually this will go into an include file, but this will be later */
863 static Scsi_Host_Template driver_template = PCI2000;
864
865 #include "scsi_module.c"