OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [scsi/] [pci2000.c] - Blame information for rev 1772

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/*+M*************************************************************************
2
 * Perceptive Solutions, Inc. PCI-2000 device driver proc support for Linux.
3
 *
4
 * Copyright (c) 1997 Perceptive Solutions, Inc.
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2, or (at your option)
9
 * any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; see the file COPYING.  If not, write to
18
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19
 *
20
 *
21
 *      File Name:              pci2000i.c
22
 *
23
 *      Revisions       1.10    Jan-21-1999
24
 *
25
 *              - Fixed sign on message to reflect proper controller name.
26
 *              - Added support for RAID status monitoring and control.
27
 *
28
 *-M*************************************************************************/
29
#define PCI2000_VERSION         "1.10"
30
 
31
#include <linux/module.h>
32
 
33
#include <linux/kernel.h>
34
#include <linux/head.h>
35
#include <linux/types.h>
36
#include <linux/string.h>
37
#include <linux/bios32.h>
38
#include <linux/pci.h>
39
#include <linux/ioport.h>
40
#include <linux/delay.h>
41
#include <linux/sched.h>
42
#include <linux/proc_fs.h>
43
#include <asm/dma.h>
44
#include <asm/system.h>
45
#include <asm/io.h>
46
#include <linux/blk.h>
47
#include "scsi.h"
48
#include "hosts.h"
49
 
50
#include "pci2000.h"
51
#include "psi_roy.h"
52
 
53
#include<linux/stat.h>
54
 
55
struct proc_dir_entry Proc_Scsi_Pci2000 =
56
        { PROC_SCSI_PCI2000, 7, "pci2000", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
57
 
58
//#define DEBUG 1
59
 
60
#ifdef DEBUG
61
#define DEB(x) x
62
#define STOP_HERE       {int st;for(st=0;st<100;st++){st=1;}}
63
#else
64
#define DEB(x)
65
#define STOP_HERE
66
#endif
67
 
68
typedef struct
69
        {
70
        ULONG           address;
71
        ULONG           length;
72
        }       SCATGATH, *PSCATGATH;
73
 
74
typedef struct
75
        {
76
        Scsi_Cmnd       *SCpnt;
77
        SCATGATH         scatGath[16];
78
        UCHAR            tag;
79
        }       DEV2000, *PDEV2000;
80
 
81
typedef struct
82
        {
83
        USHORT           basePort;
84
        USHORT           mb0;
85
        USHORT           mb1;
86
        USHORT           mb2;
87
        USHORT           mb3;
88
        USHORT           mb4;
89
        USHORT           cmd;
90
        USHORT           tag;
91
        DEV2000          dev[MAX_BUS][MAX_UNITS];
92
        }       ADAPTER2000, *PADAPTER2000;
93
 
94
#define HOSTDATA(host) ((PADAPTER2000)&host->hostdata)
95
 
96
 
97
static struct   Scsi_Host          *PsiHost[MAXADAPTER] = {NULL,};  // One for each adapter
98
static                  int                             NumAdapters = 0;
99
/****************************************************************
100
 *      Name:                   WaitReady       :LOCAL
101
 *
102
 *      Description:    Wait for controller ready.
103
 *
104
 *      Parameters:             padapter - Pointer adapter data structure.
105
 *
106
 *      Returns:                TRUE on not ready.
107
 *
108
 ****************************************************************/
109
static int WaitReady (PADAPTER2000 padapter)
110
        {
111
        ULONG   timer;
112
 
113
        timer = jiffies + TIMEOUT_COMMAND;                                                              // calculate the timeout value
114
        do      {
115
                if ( !inb_p (padapter->cmd) )
116
                        return FALSE;
117
                }       while ( timer > jiffies );                                                                      // test for timeout
118
        return TRUE;
119
        }
120
/****************************************************************
121
 *      Name:   OpDone  :LOCAL
122
 *
123
 *      Description:    Clean up operation and issue done to caller.
124
 *
125
 *      Parameters:             SCpnt   - Pointer to SCSI command structure.
126
 *                                      status  - Caller status.
127
 *
128
 *      Returns:                Nothing.
129
 *
130
 ****************************************************************/
131
static void OpDone (Scsi_Cmnd *SCpnt, ULONG status)
132
        {
133
        SCpnt->result = status;
134
        SCpnt->scsi_done (SCpnt);
135
        }
136
/****************************************************************
137
 *      Name:   Command         :LOCAL
138
 *
139
 *      Description:    Issue queued command to the PCI-2000.
140
 *
141
 *      Parameters:             padapter - Pointer to adapter information structure.
142
 *                                      cmd              - PCI-2000 command byte.
143
 *
144
 *      Returns:                Non-zero command tag if operation is accepted.
145
 *
146
 ****************************************************************/
147
static UCHAR Command (PADAPTER2000 padapter, UCHAR cmd)
148
        {
149
        outb_p (cmd, padapter->cmd);
150
        if ( WaitReady (padapter) )
151
                return 0;
152
 
153
        if ( inw_p (padapter->mb0) )
154
                return 0;
155
 
156
        return inb_p (padapter->mb1);
157
        }
158
/****************************************************************
159
 *      Name:   BuildSgList             :LOCAL
160
 *
161
 *      Description:    Build the scatter gather list for controller.
162
 *
163
 *      Parameters:             SCpnt    - Pointer to SCSI command structure.
164
 *                                      padapter - Pointer to adapter information structure.
165
 *                                      pdev     - Pointer to adapter device structure.
166
 *
167
 *      Returns:                Non-zero in not scatter gather.
168
 *
169
 ****************************************************************/
170
static int BuildSgList (Scsi_Cmnd *SCpnt, PADAPTER2000 padapter, PDEV2000 pdev)
171
        {
172
        int     z;
173
 
174
        if ( SCpnt->use_sg )
175
                {
176
                for ( z = 0;  z < SCpnt->use_sg;  z++ )
177
                        {
178
                        pdev->scatGath[z].address = virt_to_bus (((struct scatterlist *)SCpnt->request_buffer)[z].address);
179
                        pdev->scatGath[z].length = ((struct scatterlist *)SCpnt->request_buffer)[z].length;
180
                        }
181
                outl (virt_to_bus (pdev->scatGath), padapter->mb2);
182
                outl ((SCpnt->use_sg << 24) | SCpnt->request_bufflen, padapter->mb3);
183
                return FALSE;
184
                }
185
        outl (virt_to_bus (SCpnt->request_buffer), padapter->mb2);
186
        outl (SCpnt->request_bufflen, padapter->mb3);
187
        return TRUE;
188
        }
189
/*********************************************************************
190
 *      Name:   PsiRaidCmd
191
 *
192
 *      Description:    Execute a simple command.
193
 *
194
 *      Parameters:             padapter - Pointer to adapter control structure.
195
 *                                      cmd              - Roy command byte.
196
 *
197
 *      Returns:                Return error status.
198
 *
199
 ********************************************************************/
200
static int PsiRaidCmd (PADAPTER2000 padapter, char cmd)
201
        {
202
        if ( WaitReady (padapter) )                                             // test for command register ready
203
                return DID_TIME_OUT;
204
        outb_p (cmd, padapter->cmd);                                    // issue command
205
        if ( WaitReady (padapter) )                                             // wait for adapter ready
206
                return DID_TIME_OUT;
207
        return DID_OK;
208
        }
209
/****************************************************************
210
 *      Name:   Irq_Handler     :LOCAL
211
 *
212
 *      Description:    Interrupt handler.
213
 *
214
 *      Parameters:             irq             - Hardware IRQ number.
215
 *                                      dev_id  -
216
 *                                      regs    -
217
 *
218
 *      Returns:                TRUE if drive is not ready in time.
219
 *
220
 ****************************************************************/
221
static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
222
        {
223
        struct Scsi_Host   *shost = NULL;       // Pointer to host data block
224
        PADAPTER2000            padapter;               // Pointer to adapter control structure
225
        PDEV2000                        pdev;
226
        Scsi_Cmnd                  *SCpnt;
227
        UCHAR                           tag = 0;
228
        UCHAR                           tag0;
229
        ULONG                           error;
230
        int                                     pun;
231
        int                                     bus;
232
        int                                     z;
233
 
234
        DEB(printk ("\npci2000 recieved interrupt "));
235
        for ( z = 0; z < NumAdapters;  z++ )                                                                             // scan for interrupt to process
236
                {
237
                if ( PsiHost[z]->irq == (UCHAR)(irq & 0xFF) )
238
                        {
239
                        tag = inb_p (HOSTDATA(PsiHost[z])->tag);
240
                        if (  tag )
241
                                {
242
                                shost = PsiHost[z];
243
                                break;
244
                                }
245
                        }
246
                }
247
 
248
        if ( !shost )
249
                {
250
                DEB (printk ("\npci2000: not my interrupt"));
251
                return;
252
                }
253
 
254
        padapter = HOSTDATA(shost);
255
 
256
        tag0 = tag & 0x7F;                                                                                                                      // mask off the error bit
257
        for ( bus = 0;  bus < MAX_BUS;  bus++ )                                                                          // scan the busses
258
        {
259
                for ( pun = 0;  pun < MAX_UNITS;  pun++ )                                                                // scan the targets
260
                {
261
                        pdev = &padapter->dev[bus][pun];
262
                        if ( !pdev->tag )
263
                        continue;
264
                        if ( pdev->tag == tag0 )                                                                                        // is this it?
265
                                {
266
                                pdev->tag = 0;
267
                                SCpnt = pdev->SCpnt;
268
                                goto irqProceed;
269
                        }
270
                        }
271
        }
272
 
273
        outb_p (0xFF, padapter->tag);                                                                                           // clear the op interrupt
274
        outb_p (CMD_DONE, padapter->cmd);                                                                                       // complete the op
275
        return;                                                                                                                                         // done, but, with what?
276
 
277
irqProceed:;
278
        if ( tag & ERR08_TAGGED )                                                                                               // is there an error here?
279
                {
280
                if ( WaitReady (padapter) )
281
                        {
282
                        OpDone (SCpnt, DID_TIME_OUT << 16);
283
                        return;
284
                        }
285
 
286
                outb_p (tag0, padapter->mb0);                                                                           // get real error code
287
                outb_p (CMD_ERROR, padapter->cmd);
288
                if ( WaitReady (padapter) )                                                                                     // wait for controller to suck up the op
289
                        {
290
                        OpDone (SCpnt, DID_TIME_OUT << 16);
291
                        return;
292
                        }
293
 
294
                error = inl (padapter->mb0);                                                                            // get error data
295
                outb_p (0xFF, padapter->tag);                                                                           // clear the op interrupt
296
                outb_p (CMD_DONE, padapter->cmd);                                                                       // complete the op
297
 
298
                DEB (printk ("status: %lX ", error));
299
                if ( error == 0x00020002 )                                                                                      // is this error a check condition?
300
                        {
301
                        if ( bus )                                                                                                              // are we doint SCSI commands?
302
                                {
303
                                OpDone (SCpnt, (DID_OK << 16) | 2);
304
                                return;
305
                                }
306
                        if ( *SCpnt->cmnd == SCSIOP_TEST_UNIT_READY )
307
                                OpDone (SCpnt, (DRIVER_SENSE << 24) | (DID_OK << 16) | 2);      // test caller we have sense data too
308
                        else
309
                                OpDone (SCpnt, DID_ERROR << 16);
310
                        return;
311
                        }
312
                OpDone (SCpnt, DID_ERROR << 16);
313
                return;
314
                }
315
 
316
        outb_p (0xFF, padapter->tag);                                                                                   // clear the op interrupt
317
        outb_p (CMD_DONE, padapter->cmd);                                                                               // complete the op
318
        OpDone (SCpnt, DID_OK << 16);
319
        }
320
/****************************************************************
321
 *      Name:   Pci2220i_QueueCommand
322
 *
323
 *      Description:    Process a queued command from the SCSI manager.
324
 *
325
 *      Parameters:             SCpnt - Pointer to SCSI command structure.
326
 *                                      done  - Pointer to done function to call.
327
 *
328
 *      Returns:                Status code.
329
 *
330
 ****************************************************************/
331
int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
332
        {
333
        UCHAR              *cdb = (UCHAR *)SCpnt->cmnd;                                 // Pointer to SCSI CDB
334
        PADAPTER2000    padapter = HOSTDATA(SCpnt->host);                       // Pointer to adapter control structure
335
        int                             rc               = -1;                                                          // command return code
336
        UCHAR                   bus              = SCpnt->channel;
337
        UCHAR                   pun              = SCpnt->target;
338
        UCHAR                   lun              = SCpnt->lun;
339
        UCHAR                   cmd;
340
        PDEV2000                pdev     = &padapter->dev[bus][pun];
341
 
342
        if ( !done )
343
                {
344
                printk("pci2000_queuecommand: %02X: done can't be NULL\n", *cdb);
345
                return 0;
346
                }
347
 
348
        SCpnt->scsi_done = done;
349
        pdev->SCpnt = SCpnt;                                                                    // Save this command data
350
 
351
        if ( WaitReady (padapter) )
352
                {
353
                rc = DID_ERROR;
354
                goto finished;
355
                }
356
 
357
        outw_p (pun | (lun << 8), padapter->mb0);
358
 
359
        if ( bus )
360
                {
361
                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]));
362
                DEB (if(*cdb) printk ("\ntimeout_per_command: %d, timeout_total: %d, timeout: %d, internal_timout: %d", SCpnt->timeout_per_command,
363
                                                          SCpnt->timeout_total, SCpnt->timeout, SCpnt->internal_timeout));
364
                outl (SCpnt->timeout_per_command, padapter->mb1);
365
                outb_p (CMD_SCSI_TIMEOUT, padapter->cmd);
366
                if ( WaitReady (padapter) )
367
                        {
368
                        rc = DID_ERROR;
369
                        goto finished;
370
                        }
371
 
372
                outw_p (pun | (lun << 8), padapter->mb0);
373
                outw_p (SCpnt->cmd_len << 8, padapter->mb0 + 2);
374
                outl (virt_to_bus (cdb), padapter->mb1);
375
                if ( BuildSgList (SCpnt, padapter, pdev) )
376
                        cmd = CMD_SCSI_THRU;
377
                else
378
                        cmd = CMD_SCSI_THRU_SG;
379
                if ( (pdev->tag = Command (padapter, cmd)) == 0 )
380
                        rc = DID_TIME_OUT;
381
                goto finished;
382
                }
383
        else
384
                {
385
                if ( lun )
386
                        {
387
                        rc = DID_BAD_TARGET;
388
                        goto finished;
389
                        }
390
                }
391
 
392
        switch ( *cdb )
393
                {
394
                case SCSIOP_INQUIRY:                                    // inquiry CDB
395
                        if ( cdb[2] == SC_MY_RAID )
396
                                {
397
                                switch ( cdb[3] )
398
                                        {
399
                                        case MY_SCSI_REBUILD:
400
                                                OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_REBUILD) << 16);
401
                                                return 0;
402
                                        case MY_SCSI_ALARMMUTE:
403
                                                OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_MUTE) << 16);
404
                                                return 0;
405
                                        case MY_SCSI_DEMOFAIL:
406
                                                OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_FAIL) << 16);
407
                                                return 0;
408
                                        default:
409
                                                if ( SCpnt->use_sg )
410
                                                        {
411
                                                        rc = DID_ERROR;
412
                                                        goto finished;
413
                                                        }
414
                                                else
415
                                                        outl (virt_to_bus (SCpnt->request_buffer), padapter->mb2);
416
                                                outl (cdb[5], padapter->mb0);
417
                                                outl (cdb[3], padapter->mb3);
418
                                                cmd = CMD_DASD_RAID_RQ;
419
                                                break;
420
                                        }
421
                                break;
422
                                }
423
 
424
                        if ( SCpnt->use_sg )
425
                                {
426
                                outl (virt_to_bus (((struct scatterlist *)(SCpnt->request_buffer))->address), padapter->mb2);
427
                                }
428
                        else
429
                                {
430
                                outl (virt_to_bus (SCpnt->request_buffer), padapter->mb2);
431
                                }
432
                        outl (SCpnt->request_bufflen, padapter->mb3);
433
                        cmd = CMD_DASD_SCSI_INQ;
434
                        break;
435
 
436
                case SCSIOP_TEST_UNIT_READY:                    // test unit ready CDB
437
                        outl (virt_to_bus (SCpnt->sense_buffer), padapter->mb2);
438
                        outl (sizeof (SCpnt->sense_buffer), padapter->mb3);
439
                        cmd = CMD_TEST_READY;
440
                        break;
441
 
442
                case SCSIOP_READ_CAPACITY:                              // read capctiy CDB
443
                        if ( SCpnt->use_sg )
444
                                {
445
                                outl (virt_to_bus (((struct scatterlist *)(SCpnt->request_buffer))->address), padapter->mb2);
446
                                }
447
                        else
448
                                {
449
                                outl (virt_to_bus (SCpnt->request_buffer), padapter->mb2);
450
                                }
451
                        outl (8, padapter->mb3);
452
                        cmd = CMD_DASD_CAP;
453
                        break;
454
                case SCSIOP_VERIFY:                                             // verify CDB
455
                        outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
456
                        outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
457
                        cmd = CMD_READ_SG;
458
                        break;
459
                case SCSIOP_READ:                                               // read10 CDB
460
                        outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
461
                        outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
462
                        if ( BuildSgList (SCpnt, padapter, pdev) )
463
                                cmd = CMD_READ;
464
                        else
465
                                cmd = CMD_READ_SG;
466
                        break;
467
                case SCSIOP_READ6:                                              // read6  CDB
468
                        outw_p (cdb[4], padapter->mb0 + 2);
469
                        outl ((SCSI2LONG (&cdb[1])) & 0x001FFFFF, padapter->mb1);
470
                        if ( BuildSgList (SCpnt, padapter, pdev) )
471
                                cmd = CMD_READ;
472
                        else
473
                                cmd = CMD_READ_SG;
474
                        break;
475
                case SCSIOP_WRITE:                                              // write10 CDB
476
                        outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
477
                        outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
478
                        if ( BuildSgList (SCpnt, padapter, pdev) )
479
                                cmd = CMD_WRITE;
480
                        else
481
                                cmd = CMD_WRITE_SG;
482
                        break;
483
                case SCSIOP_WRITE6:                                             // write6  CDB
484
                        outw_p (cdb[4], padapter->mb0 + 2);
485
                        outl ((SCSI2LONG (&cdb[1])) & 0x001FFFFF, padapter->mb1);
486
                        if ( BuildSgList (SCpnt, padapter, pdev) )
487
                                cmd = CMD_WRITE;
488
                        else
489
                                cmd = CMD_WRITE_SG;
490
                        break;
491
                case SCSIOP_START_STOP_UNIT:
492
                        cmd = CMD_EJECT_MEDIA;
493
                        break;
494
                case SCSIOP_MEDIUM_REMOVAL:
495
                        switch ( cdb[4] )
496
                                {
497
                                case 0:
498
                                        cmd = CMD_UNLOCK_DOOR;
499
                                        break;
500
                                case 1:
501
                                        cmd = CMD_LOCK_DOOR;
502
                                        break;
503
                                default:
504
                                        cmd = 0;
505
                                        break;
506
                                }
507
                        if ( cmd )
508
                                break;
509
                default:
510
                        DEB (printk ("pci2220i_queuecommand: Unsupported command %02X\n", *cdb));
511
                        OpDone (SCpnt, DID_ERROR << 16);
512
                        return 0;
513
                }
514
 
515
        if ( (pdev->tag = Command (padapter, cmd)) == 0 )
516
                rc = DID_TIME_OUT;
517
finished:;
518
        if ( rc != -1 )
519
                OpDone (SCpnt, rc << 16);
520
        return 0;
521
        }
522
/****************************************************************
523
 *      Name:   internal_done :LOCAL
524
 *
525
 *      Description:    Done handler for non-queued commands
526
 *
527
 *      Parameters:             SCpnt - Pointer to SCSI command structure.
528
 *
529
 *      Returns:                Nothing.
530
 *
531
 ****************************************************************/
532
static void internal_done (Scsi_Cmnd * SCpnt)
533
        {
534
        SCpnt->SCp.Status++;
535
        }
536
/****************************************************************
537
 *      Name:   Pci2220i_Command
538
 *
539
 *      Description:    Process a command from the SCSI manager.
540
 *
541
 *      Parameters:             SCpnt - Pointer to SCSI command structure.
542
 *
543
 *      Returns:                Status code.
544
 *
545
 ****************************************************************/
546
int Pci2000_Command (Scsi_Cmnd *SCpnt)
547
        {
548
        DEB(printk("pci2000_command: ..calling pci2000_queuecommand\n"));
549
 
550
        Pci2000_QueueCommand (SCpnt, internal_done);
551
 
552
    SCpnt->SCp.Status = 0;
553
        while (!SCpnt->SCp.Status)
554
                barrier ();
555
        return SCpnt->result;
556
        }
557
/****************************************************************
558
 *      Name:   Pci2220i_Detect
559
 *
560
 *      Description:    Detect and initialize our boards.
561
 *
562
 *      Parameters:             tpnt - Pointer to SCSI host template structure.
563
 *
564
 *      Returns:                Number of adapters found.
565
 *
566
 ****************************************************************/
567
int Pci2000_Detect (Scsi_Host_Template *tpnt)
568
        {
569
        int                                     pci_index = 0;
570
        struct Scsi_Host   *pshost;
571
        PADAPTER2000        padapter;
572
        int                                     z, zz;
573
        int                                     setirq;
574
 
575
        if ( pcibios_present () )
576
                {
577
                for ( pci_index = 0;  pci_index <= MAXADAPTER;  ++pci_index )
578
                        {
579
                        UCHAR   pci_bus, pci_device_fn;
580
 
581
                        if ( pcibios_find_device (VENDOR_PSI, DEVICE_ROY_1, pci_index, &pci_bus, &pci_device_fn) != 0 )
582
                                break;
583
 
584
                        pshost = scsi_register (tpnt, sizeof(ADAPTER2000));
585
                        padapter = HOSTDATA(pshost);
586
 
587
                        pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &padapter->basePort);
588
                        padapter->basePort &= 0xFFFE;
589
                        DEB (printk ("\nBase Regs = %#04X", padapter->basePort));                       // get the base I/O port address
590
                        padapter->mb0   = padapter->basePort + RTR_MAILBOX;                                     // get the 32 bit mail boxes
591
                        padapter->mb1   = padapter->basePort + RTR_MAILBOX + 4;
592
                        padapter->mb2   = padapter->basePort + RTR_MAILBOX + 8;
593
                        padapter->mb3   = padapter->basePort + RTR_MAILBOX + 12;
594
                        padapter->mb4   = padapter->basePort + RTR_MAILBOX + 16;
595
                        padapter->cmd   = padapter->basePort + RTR_LOCAL_DOORBELL;                      // command register
596
                        padapter->tag   = padapter->basePort + RTR_PCI_DOORBELL;                        // tag/response register
597
 
598
                        if ( WaitReady (padapter) )
599
                                goto unregister;
600
                        outb_p (0x84, padapter->mb0);
601
                        outb_p (CMD_SPECIFY, padapter->cmd);
602
                        if ( WaitReady (padapter) )
603
                                goto unregister;
604
 
605
                        pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq);
606
                        setirq = 1;
607
                        for ( z = 0;  z < pci_index;  z++ )                                                                      // scan for shared interrupts
608
                                {
609
                                if ( PsiHost[z]->irq == pshost->irq )                                                   // if shared then, don't posses
610
                                        setirq = 0;
611
                                }
612
                        if ( setirq )                                                                                                           // if not shared, posses
613
                                {
614
                                if ( request_irq (pshost->irq, Irq_Handler, 0, "pci2000", NULL) )
615
                                        {
616
                                        printk ("Unable to allocate IRQ for PSI-2000 controller.\n");
617
                                        goto unregister;
618
                                        }
619
                                }
620
                        PsiHost[pci_index]      = pshost;                                                                               // save SCSI_HOST pointer
621
 
622
                        pshost->unique_id       = padapter->basePort;
623
                        pshost->max_id          = 16;
624
                        pshost->max_channel     = 1;
625
 
626
                        for ( zz = 0;  zz < MAX_BUS;  zz++ )
627
                                for ( z = 0; z < MAX_UNITS;  z++ )
628
                                        padapter->dev[zz][z].tag = 0;
629
 
630
                        printk("\nPSI-2000 Intelligent Storage SCSI CONTROLLER: at I/O = %X  IRQ = %d\n", padapter->basePort, pshost->irq);
631
                        printk("Version %s, Compiled %s %s\n\n", PCI2000_VERSION,  __DATE__, __TIME__);
632
                        continue;
633
unregister:;
634
                        scsi_unregister (pshost);
635
                        }
636
                }
637
        NumAdapters = pci_index;
638
        return pci_index;
639
        }
640
/****************************************************************
641
 *      Name:   Pci2220i_Abort
642
 *
643
 *      Description:    Process the Abort command from the SCSI manager.
644
 *
645
 *      Parameters:             SCpnt - Pointer to SCSI command structure.
646
 *
647
 *      Returns:                Allways snooze.
648
 *
649
 ****************************************************************/
650
int Pci2000_Abort (Scsi_Cmnd *SCpnt)
651
        {
652
        DEB (printk ("pci2000_abort\n"));
653
        return SCSI_ABORT_SNOOZE;
654
        }
655
/****************************************************************
656
 *      Name:   Pci2220i_Reset
657
 *
658
 *      Description:    Process the Reset command from the SCSI manager.
659
 *
660
 *      Parameters:             SCpnt - Pointer to SCSI command structure.
661
 *                                      flags - Flags about the reset command
662
 *
663
 *      Returns:                No active command at this time, so this means
664
 *                                      that each time we got some kind of response the
665
 *                                      last time through.  Tell the mid-level code to
666
 *                                      request sense information in order to decide what
667
 *                                      to do next.
668
 *
669
 ****************************************************************/
670
int Pci2000_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
671
        {
672
        return SCSI_RESET_PUNT;
673
        }
674
 
675
#include "sd.h"
676
 
677
/****************************************************************
678
 *      Name:   Pci2220i_BiosParam
679
 *
680
 *      Description:    Process the biosparam request from the SCSI manager to
681
 *                                      return C/H/S data.
682
 *
683
 *      Parameters:             disk - Pointer to SCSI disk structure.
684
 *                                      dev      - Major/minor number from kernel.
685
 *                                      geom - Pointer to integer array to place geometry data.
686
 *
687
 *      Returns:                zero.
688
 *
689
 ****************************************************************/
690
int Pci2000_BiosParam (Scsi_Disk *disk, kdev_t dev, int geom[])
691
        {
692
        PADAPTER2000        padapter;
693
 
694
        padapter = HOSTDATA(disk->device->host);
695
 
696
        if ( WaitReady (padapter) )
697
                return 0;
698
        outb_p (disk->device->id, padapter->mb0);
699
        outb_p (CMD_GET_PARMS, padapter->cmd);
700
        if ( WaitReady (padapter) )
701
                return 0;
702
 
703
        geom[0] = inb_p (padapter->mb2 + 3);
704
        geom[1] = inb_p (padapter->mb2 + 2);
705
        geom[2] = inw_p (padapter->mb2);
706
        return 0;
707
        }
708
 
709
 
710
#ifdef MODULE
711
/* Eventually this will go into an include file, but this will be later */
712
Scsi_Host_Template driver_template = PCI2000;
713
 
714
#include "scsi_module.c"
715
#endif
716
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.