[TG3]: Set minimal hw interrupt mitigation.
[linux-2.6/verdex.git] / drivers / scsi / pci2220i.c
blobe395e4203154fe6eeacce37da94e3ec3e5754bf4
1 /****************************************************************************
2 * Perceptive Solutions, Inc. PCI-2220I device driver for Linux.
4 * pci2220i.c - Linux Host Driver for PCI-2220I EIDE RAID Adapters
6 * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
7 * All Rights Reserved.
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.
14 * Technical updates and product information at:
15 * http://www.psidisk.com
17 * Please send questions, comments, bug reports to:
18 * tech@psidisk.com Technical Support
21 * Revisions 1.10 Mar-26-1999
22 * - Updated driver for RAID and hot reconstruct support.
24 * Revisions 1.11 Mar-26-1999
25 * - Fixed spinlock and PCI configuration.
27 * Revision 2.00 December-1-1999
28 * - Added code for the PCI-2240I controller
29 * - Added code for ATAPI devices.
30 * - Double buffer for scatter/gather support
32 * Revision 2.10 March-27-2000
33 * - Added support for dynamic DMA
35 ****************************************************************************/
37 #error Convert me to understand page+offset based scatterlists
39 //#define DEBUG 1
41 #include <linux/interrupt.h>
42 #include <linux/module.h>
43 #include <linux/kernel.h>
44 #include <linux/types.h>
45 #include <linux/string.h>
46 #include <linux/slab.h>
47 #include <linux/pci.h>
48 #include <linux/ioport.h>
49 #include <linux/delay.h>
50 #include <linux/sched.h>
51 #include <linux/proc_fs.h>
52 #include <linux/stat.h>
53 #include <linux/blkdev.h>
54 #include <linux/timer.h>
55 #include <linux/spinlock.h>
57 #include <asm/dma.h>
58 #include <asm/system.h>
59 #include <asm/io.h>
61 #include "scsi.h"
62 #include <scsi/scsi_host.h>
63 #include "pci2220i.h"
64 #include "psi_dale.h"
67 #define PCI2220I_VERSION "2.10"
68 #define READ_CMD IDE_CMD_READ_MULTIPLE
69 #define WRITE_CMD IDE_CMD_WRITE_MULTIPLE
70 #define MAX_BUS_MASTER_BLOCKS SECTORSXFER // This is the maximum we can bus master
72 #ifdef DEBUG
73 #define DEB(x) x
74 #define STOP_HERE() {int st;for(st=0;st<100;st++){st=1;}}
75 #else
76 #define DEB(x)
77 #define STOP_HERE()
78 #endif
80 #define MAXADAPTER 4 // Increase this and the sizes of the arrays below, if you need more.
83 typedef struct
85 UCHAR byte6; // device select register image
86 UCHAR spigot; // spigot number
87 UCHAR spigots[2]; // RAID spigots
88 UCHAR deviceID[2]; // device ID codes
89 USHORT sectors; // number of sectors per track
90 USHORT heads; // number of heads
91 USHORT cylinders; // number of cylinders for this device
92 USHORT spareword; // placeholder
93 ULONG blocks; // number of blocks on device
94 DISK_MIRROR DiskMirror[2]; // RAID status and control
95 ULONG lastsectorlba[2]; // last addressable sector on the drive
96 USHORT raid; // RAID active flag
97 USHORT mirrorRecon;
98 UCHAR reconOn;
99 USHORT reconCount;
100 USHORT reconIsStarting; // indicate hot reconstruct is starting
101 UCHAR cmdDrqInt; // flag for command interrupt
102 UCHAR packet; // command packet size in bytes
103 } OUR_DEVICE, *POUR_DEVICE;
105 typedef struct
107 USHORT bigD; // identity is a PCI-2240I if true, otherwise a PCI-2220I
108 USHORT atapi; // this interface is for ATAPI devices only
109 ULONG regDmaDesc; // address of the DMA discriptor register for direction of transfer
110 ULONG regDmaCmdStat; // Byte #1 of DMA command status register
111 ULONG regDmaAddrPci; // 32 bit register for PCI address of DMA
112 ULONG regDmaAddrLoc; // 32 bit register for local bus address of DMA
113 ULONG regDmaCount; // 32 bit register for DMA transfer count
114 ULONG regDmaMode; // 32 bit register for DMA mode control
115 ULONG regRemap; // 32 bit local space remap
116 ULONG regDesc; // 32 bit local region descriptor
117 ULONG regRange; // 32 bit local range
118 ULONG regIrqControl; // 16 bit Interrupt enable/disable and status
119 ULONG regScratchPad; // scratch pad I/O base address
120 ULONG regBase; // Base I/O register for data space
121 ULONG regData; // data register I/O address
122 ULONG regError; // error register I/O address
123 ULONG regSectCount; // sector count register I/O address
124 ULONG regLba0; // least significant byte of LBA
125 ULONG regLba8; // next least significant byte of LBA
126 ULONG regLba16; // next most significan byte of LBA
127 ULONG regLba24; // head and most 4 significant bits of LBA
128 ULONG regStatCmd; // status on read and command on write register
129 ULONG regStatSel; // board status on read and spigot select on write register
130 ULONG regFail; // fail bits control register
131 ULONG regAltStat; // alternate status and drive control register
132 ULONG basePort; // PLX base I/O port
133 USHORT timingMode; // timing mode currently set for adapter
134 USHORT timingPIO; // TRUE if PIO timing is active
135 struct pci_dev *pcidev;
136 ULONG timingAddress; // address to use on adapter for current timing mode
137 ULONG irqOwned; // owned IRQ or zero if shared
138 UCHAR numberOfDrives; // saved number of drives on this controller
139 UCHAR failRegister; // current inverted data in fail register
140 OUR_DEVICE device[BIGD_MAXDRIVES];
141 DISK_MIRROR *raidData[BIGD_MAXDRIVES];
142 ULONG startSector;
143 USHORT sectorCount;
144 ULONG readCount;
145 UCHAR *currentSgBuffer;
146 ULONG currentSgCount;
147 USHORT nextSg;
148 UCHAR cmd;
149 Scsi_Cmnd *SCpnt;
150 POUR_DEVICE pdev; // current device opearating on
151 USHORT devInReconIndex;
152 USHORT expectingIRQ;
153 USHORT reconOn; // Hot reconstruct is to be done.
154 USHORT reconPhase; // Hot reconstruct operation is in progress.
155 ULONG reconSize;
156 USHORT demoFail; // flag for RAID failure demonstration
157 USHORT survivor;
158 USHORT failinprog;
159 struct timer_list reconTimer;
160 struct timer_list timer;
161 UCHAR *kBuffer;
162 dma_addr_t kBufferDma;
163 UCHAR reqSense;
164 UCHAR atapiCdb[16];
165 UCHAR atapiSpecial;
166 } ADAPTER2220I, *PADAPTER2220I;
168 #define HOSTDATA(host) ((PADAPTER2220I)&host->hostdata)
170 #define RECON_PHASE_READY 0x01
171 #define RECON_PHASE_COPY 0x02
172 #define RECON_PHASE_UPDATE 0x03
173 #define RECON_PHASE_LAST 0x04
174 #define RECON_PHASE_END 0x07
175 #define RECON_PHASE_MARKING 0x80
176 #define RECON_PHASE_FAILOVER 0xFF
178 static struct Scsi_Host *PsiHost[MAXADAPTER] = {NULL,}; // One for each adapter
179 static int NumAdapters = 0;
180 static int Installed = 0;
181 static SETUP DaleSetup;
182 static DISK_MIRROR DiskMirror[BIGD_MAXDRIVES];
183 static ULONG ModeArray[] = {DALE_DATA_MODE2, DALE_DATA_MODE3, DALE_DATA_MODE4, DALE_DATA_MODE5};
184 static ULONG ModeArray2[] = {BIGD_DATA_MODE2, BIGD_DATA_MODE3, BIGD_DATA_MODE4, BIGD_DATA_MODE5};
186 static void ReconTimerExpiry (unsigned long data);
188 /*******************************************************************************************************
189 * Name: Alarm
191 * Description: Sound the for the given device
193 * Parameters: padapter - Pointer adapter data structure.
194 * device - Device number.
196 * Returns: Nothing.
198 ******************************************************************************************************/
199 static void Alarm (PADAPTER2220I padapter, UCHAR device)
201 UCHAR zc;
203 if ( padapter->bigD )
205 zc = device | (FAIL_ANY | FAIL_AUDIBLE);
206 if ( padapter->failRegister & FAIL_ANY )
207 zc |= FAIL_MULTIPLE;
209 padapter->failRegister = zc;
210 outb_p (~zc, padapter->regFail);
212 else
213 outb_p (0x3C | (1 << device), padapter->regFail); // sound alarm and set fail light
215 /****************************************************************
216 * Name: MuteAlarm :LOCAL
218 * Description: Mute the audible alarm.
220 * Parameters: padapter - Pointer adapter data structure.
222 * Returns: TRUE if drive does not assert DRQ in time.
224 ****************************************************************/
225 static void MuteAlarm (PADAPTER2220I padapter)
227 UCHAR old;
229 if ( padapter->bigD )
231 padapter->failRegister &= ~FAIL_AUDIBLE;
232 outb_p (~padapter->failRegister, padapter->regFail);
234 else
236 old = (inb_p (padapter->regStatSel) >> 3) | (inb_p (padapter->regStatSel) & 0x83);
237 outb_p (old | 0x40, padapter->regFail);
240 /****************************************************************
241 * Name: WaitReady :LOCAL
243 * Description: Wait for device ready.
245 * Parameters: padapter - Pointer adapter data structure.
247 * Returns: TRUE if drive does not assert DRQ in time.
249 ****************************************************************/
250 static int WaitReady (PADAPTER2220I padapter)
252 ULONG z;
253 UCHAR status;
255 for ( z = 0; z < (TIMEOUT_READY * 4); z++ )
257 status = inb_p (padapter->regStatCmd);
258 if ( (status & (IDE_STATUS_DRDY | IDE_STATUS_BUSY)) == IDE_STATUS_DRDY )
259 return 0;
260 udelay (250);
262 return status;
264 /****************************************************************
265 * Name: WaitReadyReset :LOCAL
267 * Description: Wait for device ready.
269 * Parameters: padapter - Pointer adapter data structure.
271 * Returns: TRUE if drive does not assert DRQ in time.
273 ****************************************************************/
274 static int WaitReadyReset (PADAPTER2220I padapter)
276 ULONG z;
277 UCHAR status;
279 for ( z = 0; z < (125 * 16); z++ ) // wait up to 1/4 second
281 status = inb_p (padapter->regStatCmd);
282 if ( (status & (IDE_STATUS_DRDY | IDE_STATUS_BUSY)) == IDE_STATUS_DRDY )
284 DEB (printk ("\nPCI2220I: Reset took %ld mSec to be ready", z / 8));
285 return 0;
287 udelay (125);
289 DEB (printk ("\nPCI2220I: Reset took more than 2 Seconds to come ready, Disk Failure"));
290 return status;
292 /****************************************************************
293 * Name: WaitDrq :LOCAL
295 * Description: Wait for device ready for data transfer.
297 * Parameters: padapter - Pointer adapter data structure.
299 * Returns: TRUE if drive does not assert DRQ in time.
301 ****************************************************************/
302 static int WaitDrq (PADAPTER2220I padapter)
304 ULONG z;
305 UCHAR status;
307 for ( z = 0; z < (TIMEOUT_DRQ * 4); z++ )
309 status = inb_p (padapter->regStatCmd);
310 if ( status & IDE_STATUS_DRQ )
311 return 0;
312 udelay (250);
314 return status;
316 /****************************************************************
317 * Name: AtapiWaitReady :LOCAL
319 * Description: Wait for device busy and DRQ to be cleared.
321 * Parameters: padapter - Pointer adapter data structure.
322 * msec - Number of milliseconds to wait.
324 * Returns: TRUE if drive does not clear busy in time.
326 ****************************************************************/
327 static int AtapiWaitReady (PADAPTER2220I padapter, int msec)
329 int z;
331 for ( z = 0; z < (msec * 16); z++ )
333 if ( !(inb_p (padapter->regStatCmd) & (IDE_STATUS_BUSY | IDE_STATUS_DRQ)) )
334 return FALSE;
335 udelay (125);
337 return TRUE;
339 /****************************************************************
340 * Name: AtapiWaitDrq :LOCAL
342 * Description: Wait for device ready for data transfer.
344 * Parameters: padapter - Pointer adapter data structure.
345 * msec - Number of milliseconds to wait.
347 * Returns: TRUE if drive does not assert DRQ in time.
349 ****************************************************************/
350 static int AtapiWaitDrq (PADAPTER2220I padapter, int msec)
352 ULONG z;
354 for ( z = 0; z < (msec * 16); z++ )
356 if ( inb_p (padapter->regStatCmd) & IDE_STATUS_DRQ )
357 return 0;
358 udelay (128);
360 return TRUE;
362 /****************************************************************
363 * Name: HardReset :LOCAL
365 * Description: Wait for device ready for data transfer.
367 * Parameters: padapter - Pointer adapter data structure.
368 * pdev - Pointer to device.
369 * spigot - Spigot number.
371 * Returns: TRUE if drive does not assert DRQ in time.
373 ****************************************************************/
374 static int HardReset (PADAPTER2220I padapter, POUR_DEVICE pdev, UCHAR spigot)
376 DEB (printk ("\npci2220i:RESET spigot = %X devices = %d, %d", spigot, pdev->deviceID[0], pdev->deviceID[1]));
377 mdelay (100); // just wait 100 mSec to let drives flush
378 SelectSpigot (padapter, spigot | SEL_IRQ_OFF);
380 outb_p (0x0E, padapter->regAltStat); // reset the suvivor
381 udelay (100); // wait a little
382 outb_p (0x08, padapter->regAltStat); // clear the reset
383 udelay (100);
385 outb_p (0xA0, padapter->regLba24); // select the master drive
386 if ( WaitReadyReset (padapter) )
388 DEB (printk ("\npci2220i: master not ready after reset"));
389 return TRUE;
391 outb_p (0xB0, padapter->regLba24); // try the slave drive
392 if ( (inb_p (padapter->regStatCmd) & (IDE_STATUS_DRDY | IDE_STATUS_BUSY)) == IDE_STATUS_DRDY )
394 DEB (printk ("\nPCI2220I: initializing slave drive on spigot %X", spigot));
395 outb_p (SECTORSXFER, padapter->regSectCount);
396 WriteCommand (padapter, IDE_CMD_SET_MULTIPLE);
397 if ( WaitReady (padapter) )
399 DEB (printk ("\npci2220i: slave not ready after set multiple"));
400 return TRUE;
404 outb_p (0xA0, padapter->regLba24); // select the drive
405 outb_p (SECTORSXFER, padapter->regSectCount);
406 WriteCommand (padapter, IDE_CMD_SET_MULTIPLE);
407 if ( WaitReady (padapter) )
409 DEB (printk ("\npci2220i: master not ready after set multiple"));
410 return TRUE;
412 return FALSE;
414 /****************************************************************
415 * Name: AtapiReset :LOCAL
417 * Description: Wait for device ready for data transfer.
419 * Parameters: padapter - Pointer adapter data structure.
420 * pdev - Pointer to device.
422 * Returns: TRUE if drive does not come ready.
424 ****************************************************************/
425 static int AtapiReset (PADAPTER2220I padapter, POUR_DEVICE pdev)
427 SelectSpigot (padapter, pdev->spigot);
428 AtapiDevice (padapter, pdev->byte6);
429 AtapiCountLo (padapter, 0);
430 AtapiCountHi (padapter, 0);
431 WriteCommand (padapter, IDE_COMMAND_ATAPI_RESET);
432 udelay (125);
433 if ( AtapiWaitReady (padapter, 1000) )
434 return TRUE;
435 if ( inb_p (padapter->regStatCmd) || (inb_p (padapter->regLba8) != 0x14) || (inb_p (padapter->regLba16) != 0xEB) )
436 return TRUE;
437 return FALSE;
439 /****************************************************************
440 * Name: WalkScatGath :LOCAL
442 * Description: Transfer data to/from scatter/gather buffers.
444 * Parameters: padapter - Pointer adapter data structure.
445 * datain - TRUE if data read.
446 * length - Number of bytes to transfer.
448 * Returns: Nothing.
450 ****************************************************************/
451 static void WalkScatGath (PADAPTER2220I padapter, UCHAR datain, ULONG length)
453 ULONG count;
454 UCHAR *buffer = padapter->kBuffer;
456 while ( length )
458 count = ( length > padapter->currentSgCount ) ? padapter->currentSgCount : length;
460 if ( datain )
461 memcpy (padapter->currentSgBuffer, buffer, count);
462 else
463 memcpy (buffer, padapter->currentSgBuffer, count);
465 padapter->currentSgCount -= count;
466 if ( !padapter->currentSgCount )
468 if ( padapter->nextSg < padapter->SCpnt->use_sg )
470 padapter->currentSgBuffer = ((struct scatterlist *)padapter->SCpnt->request_buffer)[padapter->nextSg].address;
471 padapter->currentSgCount = ((struct scatterlist *)padapter->SCpnt->request_buffer)[padapter->nextSg].length;
472 padapter->nextSg++;
475 else
476 padapter->currentSgBuffer += count;
478 length -= count;
479 buffer += count;
482 /****************************************************************
483 * Name: BusMaster :LOCAL
485 * Description: Do a bus master I/O.
487 * Parameters: padapter - Pointer adapter data structure.
488 * datain - TRUE if data read.
489 * irq - TRUE if bus master interrupt expected.
491 * Returns: Nothing.
493 ****************************************************************/
494 static void BusMaster (PADAPTER2220I padapter, UCHAR datain, UCHAR irq)
496 ULONG zl;
498 zl = ( padapter->sectorCount > MAX_BUS_MASTER_BLOCKS ) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
499 padapter->sectorCount -= zl;
500 zl *= (ULONG)BYTES_PER_SECTOR;
502 if ( datain )
504 padapter->readCount = zl;
505 outb_p (8, padapter->regDmaDesc); // read operation
506 if ( padapter->bigD )
508 if ( irq && !padapter->sectorCount )
509 outb_p (0x0C, padapter->regDmaMode); // interrupt on
510 else
511 outb_p (0x08, padapter->regDmaMode); // no interrupt
513 else
515 if ( irq && !padapter->sectorCount )
516 outb_p (0x05, padapter->regDmaMode); // interrupt on
517 else
518 outb_p (0x01, padapter->regDmaMode); // no interrupt
521 else
523 outb_p (0x00, padapter->regDmaDesc); // write operation
524 if ( padapter->bigD )
525 outb_p (0x08, padapter->regDmaMode); // no interrupt
526 else
527 outb_p (0x01, padapter->regDmaMode); // no interrupt
528 WalkScatGath (padapter, FALSE, zl);
531 outl (padapter->timingAddress, padapter->regDmaAddrLoc);
532 outl (padapter->kBufferDma, padapter->regDmaAddrPci);
533 outl (zl, padapter->regDmaCount);
534 outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear
536 /****************************************************************
537 * Name: AtapiBusMaster :LOCAL
539 * Description: Do a bus master I/O.
541 * Parameters: padapter - Pointer adapter data structure.
542 * datain - TRUE if data read.
543 * length - Number of bytes to transfer.
545 * Returns: Nothing.
547 ****************************************************************/
548 static void AtapiBusMaster (PADAPTER2220I padapter, UCHAR datain, ULONG length)
550 outl (padapter->timingAddress, padapter->regDmaAddrLoc);
551 outl (padapter->kBufferDma, padapter->regDmaAddrPci);
552 outl (length, padapter->regDmaCount);
553 if ( datain )
555 if ( padapter->readCount )
556 WalkScatGath (padapter, TRUE, padapter->readCount);
557 outb_p (0x08, padapter->regDmaDesc); // read operation
558 outb_p (0x08, padapter->regDmaMode); // no interrupt
559 padapter->readCount = length;
561 else
563 outb_p (0x00, padapter->regDmaDesc); // write operation
564 outb_p (0x08, padapter->regDmaMode); // no interrupt
565 if ( !padapter->atapiSpecial )
566 WalkScatGath (padapter, FALSE, length);
568 outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear
570 /****************************************************************
571 * Name: WriteData :LOCAL
573 * Description: Write data to device.
575 * Parameters: padapter - Pointer adapter data structure.
577 * Returns: TRUE if drive does not assert DRQ in time.
579 ****************************************************************/
580 static int WriteData (PADAPTER2220I padapter)
582 ULONG zl;
584 if ( !WaitDrq (padapter) )
586 if ( padapter->timingPIO )
588 zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
589 WalkScatGath (padapter, FALSE, zl * BYTES_PER_SECTOR);
590 outsw (padapter->regData, padapter->kBuffer, zl * (BYTES_PER_SECTOR / 2));
591 padapter->sectorCount -= zl;
593 else
594 BusMaster (padapter, 0, 0);
595 return 0;
597 padapter->cmd = 0; // null out the command byte
598 return 1;
600 /****************************************************************
601 * Name: WriteDataBoth :LOCAL
603 * Description: Write data to device.
605 * Parameters: padapter - Pointer to adapter structure.
606 * pdev - Pointer to device structure
608 * Returns: Index + 1 of drive not failed or zero for OK.
610 ****************************************************************/
611 static int WriteDataBoth (PADAPTER2220I padapter, POUR_DEVICE pdev)
613 ULONG zl;
614 UCHAR status0, status1;
616 SelectSpigot (padapter, pdev->spigots[0]);
617 status0 = WaitDrq (padapter);
618 if ( !status0 )
620 SelectSpigot (padapter, pdev->spigots[1]);
621 status1 = WaitDrq (padapter);
622 if ( !status1 )
624 SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1] | padapter->bigD);
625 if ( padapter->timingPIO )
627 zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
628 WalkScatGath (padapter, FALSE, zl * BYTES_PER_SECTOR);
629 outsw (padapter->regData, padapter->kBuffer, zl * (BYTES_PER_SECTOR / 2));
630 padapter->sectorCount -= zl;
632 else
633 BusMaster (padapter, 0, 0);
634 return 0;
637 padapter->cmd = 0; // null out the command byte
638 if ( status0 )
639 return 2;
640 return 1;
642 /****************************************************************
643 * Name: IdeCmd :LOCAL
645 * Description: Process an IDE command.
647 * Parameters: padapter - Pointer adapter data structure.
648 * pdev - Pointer to device.
650 * Returns: Zero if no error or status register contents on error.
652 ****************************************************************/
653 static UCHAR IdeCmd (PADAPTER2220I padapter, POUR_DEVICE pdev)
655 UCHAR status;
657 SelectSpigot (padapter, pdev->spigot | padapter->bigD); // select the spigot
658 outb_p (pdev->byte6 | ((UCHAR *)(&padapter->startSector))[3], padapter->regLba24); // select the drive
659 status = WaitReady (padapter);
660 if ( !status )
662 outb_p (padapter->sectorCount, padapter->regSectCount);
663 outb_p (((UCHAR *)(&padapter->startSector))[0], padapter->regLba0);
664 outb_p (((UCHAR *)(&padapter->startSector))[1], padapter->regLba8);
665 outb_p (((UCHAR *)(&padapter->startSector))[2], padapter->regLba16);
666 padapter->expectingIRQ = TRUE;
667 WriteCommand (padapter, padapter->cmd);
668 return 0;
671 padapter->cmd = 0; // null out the command byte
672 return status;
674 /****************************************************************
675 * Name: IdeCmdBoth :LOCAL
677 * Description: Process an IDE command to both drivers.
679 * Parameters: padapter - Pointer adapter data structure.
680 * pdev - Pointer to device structure
682 * Returns: Index + 1 of drive not failed or zero for OK.
684 ****************************************************************/
685 static UCHAR IdeCmdBoth (PADAPTER2220I padapter, POUR_DEVICE pdev)
687 UCHAR status0;
688 UCHAR status1;
690 SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1]); // select the spigots
691 outb_p (padapter->pdev->byte6 | ((UCHAR *)(&padapter->startSector))[3], padapter->regLba24);// select the drive
692 SelectSpigot (padapter, pdev->spigots[0]);
693 status0 = WaitReady (padapter);
694 if ( !status0 )
696 SelectSpigot (padapter, pdev->spigots[1]);
697 status1 = WaitReady (padapter);
698 if ( !status1 )
700 SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1] | padapter->bigD);
701 outb_p (padapter->sectorCount, padapter->regSectCount);
702 outb_p (((UCHAR *)(&padapter->startSector))[0], padapter->regLba0);
703 outb_p (((UCHAR *)(&padapter->startSector))[1], padapter->regLba8);
704 outb_p (((UCHAR *)(&padapter->startSector))[2], padapter->regLba16);
705 padapter->expectingIRQ = TRUE;
706 WriteCommand (padapter, padapter->cmd);
707 return 0;
710 padapter->cmd = 0; // null out the command byte
711 if ( status0 )
712 return 2;
713 return 1;
715 /****************************************************************
716 * Name: OpDone :LOCAL
718 * Description: Complete an operatoin done sequence.
720 * Parameters: padapter - Pointer to host data block.
721 * spigot - Spigot select code.
722 * device - Device byte code.
724 * Returns: Nothing.
726 ****************************************************************/
727 static void OpDone (PADAPTER2220I padapter, ULONG result)
729 Scsi_Cmnd *SCpnt = padapter->SCpnt;
731 if ( padapter->reconPhase )
733 padapter->reconPhase = 0;
734 if ( padapter->SCpnt )
736 Pci2220i_QueueCommand (SCpnt, SCpnt->scsi_done);
738 else
740 if ( padapter->reconOn )
742 ReconTimerExpiry ((unsigned long)padapter);
746 else
748 padapter->cmd = 0;
749 padapter->SCpnt = NULL;
750 padapter->pdev = NULL;
751 SCpnt->result = result;
752 SCpnt->scsi_done (SCpnt);
753 if ( padapter->reconOn && !padapter->reconTimer.data )
755 padapter->reconTimer.expires = jiffies + (HZ / 4); // start in 1/4 second
756 padapter->reconTimer.data = (unsigned long)padapter;
757 add_timer (&padapter->reconTimer);
761 /****************************************************************
762 * Name: InlineIdentify :LOCAL
764 * Description: Do an intline inquiry on a drive.
766 * Parameters: padapter - Pointer to host data block.
767 * spigot - Spigot select code.
768 * device - Device byte code.
770 * Returns: Last addressable sector or zero if none.
772 ****************************************************************/
773 static ULONG InlineIdentify (PADAPTER2220I padapter, UCHAR spigot, UCHAR device)
775 PIDENTIFY_DATA pid = (PIDENTIFY_DATA)padapter->kBuffer;
777 SelectSpigot (padapter, spigot | SEL_IRQ_OFF); // select the spigot
778 outb_p ((device << 4) | 0xA0, padapter->regLba24); // select the drive
779 if ( WaitReady (padapter) )
780 return 0;
781 WriteCommand (padapter, IDE_COMMAND_IDENTIFY);
782 if ( WaitDrq (padapter) )
783 return 0;
784 insw (padapter->regData, padapter->kBuffer, sizeof (IDENTIFY_DATA) >> 1);
785 return (pid->LBATotalSectors - 1);
787 /****************************************************************
788 * Name: AtapiIdentify :LOCAL
790 * Description: Do an intline inquiry on a drive.
792 * Parameters: padapter - Pointer to host data block.
793 * pdev - Pointer to device table.
795 * Returns: TRUE on error.
797 ****************************************************************/
798 static ULONG AtapiIdentify (PADAPTER2220I padapter, POUR_DEVICE pdev)
800 ATAPI_GENERAL_0 ag0;
801 USHORT zs;
802 int z;
804 AtapiDevice (padapter, pdev->byte6);
805 WriteCommand (padapter, IDE_COMMAND_ATAPI_IDENTIFY);
806 if ( AtapiWaitDrq (padapter, 3000) )
807 return TRUE;
809 *(USHORT *)&ag0 = inw_p (padapter->regData);
810 for ( z = 0; z < 255; z++ )
811 zs = inw_p (padapter->regData);
813 if ( ag0.ProtocolType == 2 )
815 if ( ag0.CmdDrqType == 1 )
816 pdev->cmdDrqInt = TRUE;
817 switch ( ag0.CmdPacketSize )
819 case 0:
820 pdev->packet = 6;
821 break;
822 case 1:
823 pdev->packet = 8;
824 break;
825 default:
826 pdev->packet = 6;
827 break;
829 return FALSE;
831 return TRUE;
833 /****************************************************************
834 * Name: Atapi2Scsi
836 * Description: Convert ATAPI data to SCSI data.
838 * Parameters: padapter - Pointer adapter data structure.
839 * SCpnt - Pointer to SCSI command structure.
841 * Returns: Nothing.
843 ****************************************************************/
844 void Atapi2Scsi (PADAPTER2220I padapter, Scsi_Cmnd *SCpnt)
846 UCHAR *buff = padapter->currentSgBuffer;
848 switch ( SCpnt->cmnd[0] )
850 case SCSIOP_MODE_SENSE:
851 buff[0] = padapter->kBuffer[1];
852 buff[1] = padapter->kBuffer[2];
853 buff[2] = padapter->kBuffer[3];
854 buff[3] = padapter->kBuffer[7];
855 memcpy (&buff[4], &padapter->kBuffer[8], padapter->atapiCdb[8] - 8);
856 break;
857 case SCSIOP_INQUIRY:
858 padapter->kBuffer[2] = 2;
859 memcpy (buff, padapter->kBuffer, padapter->currentSgCount);
860 break;
861 default:
862 if ( padapter->readCount )
863 WalkScatGath (padapter, TRUE, padapter->readCount);
864 break;
867 /****************************************************************
868 * Name: Scsi2Atapi
870 * Description: Convert SCSI packet command to Atapi packet command.
872 * Parameters: padapter - Pointer adapter data structure.
873 * SCpnt - Pointer to SCSI command structure.
875 * Returns: Nothing.
877 ****************************************************************/
878 static void Scsi2Atapi (PADAPTER2220I padapter, Scsi_Cmnd *SCpnt)
880 UCHAR *cdb = SCpnt->cmnd;
881 UCHAR *buff = padapter->currentSgBuffer;
883 switch (cdb[0])
885 case SCSIOP_READ6:
886 padapter->atapiCdb[0] = SCSIOP_READ;
887 padapter->atapiCdb[1] = cdb[1] & 0xE0;
888 padapter->atapiCdb[3] = cdb[1] & 0x1F;
889 padapter->atapiCdb[4] = cdb[2];
890 padapter->atapiCdb[5] = cdb[3];
891 padapter->atapiCdb[8] = cdb[4];
892 padapter->atapiCdb[9] = cdb[5];
893 break;
894 case SCSIOP_WRITE6:
895 padapter->atapiCdb[0] = SCSIOP_WRITE;
896 padapter->atapiCdb[1] = cdb[1] & 0xE0;
897 padapter->atapiCdb[3] = cdb[1] & 0x1F;
898 padapter->atapiCdb[4] = cdb[2];
899 padapter->atapiCdb[5] = cdb[3];
900 padapter->atapiCdb[8] = cdb[4];
901 padapter->atapiCdb[9] = cdb[5];
902 break;
903 case SCSIOP_MODE_SENSE:
904 padapter->atapiCdb[0] = SCSIOP_MODE_SENSE10;
905 padapter->atapiCdb[2] = cdb[2];
906 padapter->atapiCdb[8] = cdb[4] + 4;
907 break;
909 case SCSIOP_MODE_SELECT:
910 padapter->atapiSpecial = TRUE;
911 padapter->atapiCdb[0] = SCSIOP_MODE_SELECT10;
912 padapter->atapiCdb[1] = cdb[1] | 0x10;
913 memcpy (padapter->kBuffer, buff, 4);
914 padapter->kBuffer[4] = padapter->kBuffer[5] = 0;
915 padapter->kBuffer[6] = padapter->kBuffer[7] = 0;
916 memcpy (&padapter->kBuffer[8], &buff[4], cdb[4] - 4);
917 padapter->atapiCdb[8] = cdb[4] + 4;
918 break;
921 /****************************************************************
922 * Name: AtapiSendCdb
924 * Description: Send the CDB packet to the device.
926 * Parameters: padapter - Pointer adapter data structure.
927 * pdev - Pointer to device.
928 * cdb - Pointer to 16 byte SCSI cdb.
930 * Returns: Nothing.
932 ****************************************************************/
933 static void AtapiSendCdb (PADAPTER2220I padapter, POUR_DEVICE pdev, CHAR *cdb)
935 DEB (printk ("\nPCI2242I: CDB: %X %X %X %X %X %X %X %X %X %X %X %X", cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]));
936 outsw (padapter->regData, cdb, pdev->packet);
938 /****************************************************************
939 * Name: AtapiRequestSense
941 * Description: Send the CDB packet to the device.
943 * Parameters: padapter - Pointer adapter data structure.
944 * pdev - Pointer to device.
945 * SCpnt - Pointer to SCSI command structure.
946 * pass - If true then this is the second pass to send cdb.
948 * Returns: TRUE on error.
950 ****************************************************************/
951 static int AtapiRequestSense (PADAPTER2220I padapter, POUR_DEVICE pdev, Scsi_Cmnd *SCpnt, UCHAR pass)
953 UCHAR cdb[16] = {SCSIOP_REQUEST_SENSE,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0};
955 DEB (printk ("\nPCI2242I: AUTO REQUEST SENSE"));
956 cdb[4] = (UCHAR)(sizeof (SCpnt->sense_buffer));
957 if ( !pass )
959 padapter->reqSense = TRUE;
960 AtapiCountLo (padapter, cdb[4]);
961 AtapiCountHi (padapter, 0);
962 outb_p (0, padapter->regError);
963 WriteCommand (padapter, IDE_COMMAND_ATAPI_PACKET);
964 if ( pdev->cmdDrqInt )
965 return FALSE;
967 if ( AtapiWaitDrq (padapter, 500) )
968 return TRUE;
970 AtapiSendCdb (padapter, pdev, cdb);
971 return FALSE;
973 /****************************************************************
974 * Name: InlineReadSignature :LOCAL
976 * Description: Do an inline read RAID sigature.
978 * Parameters: padapter - Pointer adapter data structure.
979 * pdev - Pointer to device.
980 * index - index of data to read.
982 * Returns: Zero if no error or status register contents on error.
984 ****************************************************************/
985 static UCHAR InlineReadSignature (PADAPTER2220I padapter, POUR_DEVICE pdev, int index)
987 UCHAR status;
988 ULONG zl = pdev->lastsectorlba[index];
990 SelectSpigot (padapter, pdev->spigots[index] | SEL_IRQ_OFF); // select the spigot without interrupts
991 outb_p (pdev->byte6 | ((UCHAR *)&zl)[3], padapter->regLba24);
992 status = WaitReady (padapter);
993 if ( !status )
995 outb_p (((UCHAR *)&zl)[2], padapter->regLba16);
996 outb_p (((UCHAR *)&zl)[1], padapter->regLba8);
997 outb_p (((UCHAR *)&zl)[0], padapter->regLba0);
998 outb_p (1, padapter->regSectCount);
999 WriteCommand (padapter, IDE_COMMAND_READ);
1000 status = WaitDrq (padapter);
1001 if ( !status )
1003 insw (padapter->regData, padapter->kBuffer, BYTES_PER_SECTOR / 2);
1004 ((ULONG *)(&pdev->DiskMirror[index]))[0] = ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[0];
1005 ((ULONG *)(&pdev->DiskMirror[index]))[1] = ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[1];
1006 // some drives assert DRQ before IRQ so let's make sure we clear the IRQ
1007 WaitReady (padapter);
1008 return 0;
1011 return status;
1013 /****************************************************************
1014 * Name: DecodeError :LOCAL
1016 * Description: Decode and process device errors.
1018 * Parameters: padapter - Pointer to adapter data.
1019 * status - Status register code.
1021 * Returns: The driver status code.
1023 ****************************************************************/
1024 static ULONG DecodeError (PADAPTER2220I padapter, UCHAR status)
1026 UCHAR error;
1028 padapter->expectingIRQ = 0;
1029 if ( status & IDE_STATUS_WRITE_FAULT )
1031 return DID_PARITY << 16;
1033 if ( status & IDE_STATUS_BUSY )
1034 return DID_BUS_BUSY << 16;
1036 error = inb_p (padapter->regError);
1037 DEB(printk ("\npci2220i error register: %x", error));
1038 switch ( error )
1040 case IDE_ERROR_AMNF:
1041 case IDE_ERROR_TKONF:
1042 case IDE_ERROR_ABRT:
1043 case IDE_ERROR_IDFN:
1044 case IDE_ERROR_UNC:
1045 case IDE_ERROR_BBK:
1046 default:
1047 return DID_ERROR << 16;
1049 return DID_ERROR << 16;
1051 /****************************************************************
1052 * Name: StartTimer :LOCAL
1054 * Description: Start the timer.
1056 * Parameters: ipadapter - Pointer adapter data structure.
1058 * Returns: Nothing.
1060 ****************************************************************/
1061 static void StartTimer (PADAPTER2220I padapter)
1063 padapter->timer.expires = jiffies + TIMEOUT_DATA;
1064 add_timer (&padapter->timer);
1066 /****************************************************************
1067 * Name: WriteSignature :LOCAL
1069 * Description: Start the timer.
1071 * Parameters: padapter - Pointer adapter data structure.
1072 * pdev - Pointer to our device.
1073 * spigot - Selected spigot.
1074 * index - index of mirror signature on device.
1076 * Returns: TRUE on any error.
1078 ****************************************************************/
1079 static int WriteSignature (PADAPTER2220I padapter, POUR_DEVICE pdev, UCHAR spigot, int index)
1081 ULONG zl;
1083 SelectSpigot (padapter, spigot);
1084 zl = pdev->lastsectorlba[index];
1085 outb_p (pdev->byte6 | ((UCHAR *)&zl)[3], padapter->regLba24);
1086 outb_p (((UCHAR *)&zl)[2], padapter->regLba16);
1087 outb_p (((UCHAR *)&zl)[1], padapter->regLba8);
1088 outb_p (((UCHAR *)&zl)[0], padapter->regLba0);
1089 outb_p (1, padapter->regSectCount);
1091 WriteCommand (padapter, IDE_COMMAND_WRITE);
1092 if ( WaitDrq (padapter) )
1093 return TRUE;
1094 StartTimer (padapter);
1095 padapter->expectingIRQ = TRUE;
1097 ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[0] = ((ULONG *)(&pdev->DiskMirror[index]))[0];
1098 ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[1] = ((ULONG *)(&pdev->DiskMirror[index]))[1];
1099 outsw (padapter->regData, padapter->kBuffer, BYTES_PER_SECTOR / 2);
1100 return FALSE;
1102 /*******************************************************************************************************
1103 * Name: InitFailover
1105 * Description: This is the beginning of the failover routine
1107 * Parameters: SCpnt - Pointer to SCSI command structure.
1108 * padapter - Pointer adapter data structure.
1109 * pdev - Pointer to our device.
1111 * Returns: TRUE on error.
1113 ******************************************************************************************************/
1114 static int InitFailover (PADAPTER2220I padapter, POUR_DEVICE pdev)
1116 UCHAR spigot;
1118 DEB (printk ("\npci2220i: Initialize failover process - survivor = %d", pdev->deviceID[padapter->survivor]));
1119 pdev->raid = FALSE; //initializes system for non raid mode
1120 pdev->reconOn = FALSE;
1121 spigot = pdev->spigots[padapter->survivor];
1123 if ( pdev->DiskMirror[padapter->survivor].status & UCBF_REBUILD )
1125 DEB (printk ("\n failed, is survivor"));
1126 return (TRUE);
1129 if ( HardReset (padapter, pdev, spigot) )
1131 DEB (printk ("\n failed, reset"));
1132 return TRUE;
1135 Alarm (padapter, pdev->deviceID[padapter->survivor ^ 1]);
1136 pdev->DiskMirror[padapter->survivor].status = UCBF_MIRRORED | UCBF_SURVIVOR; //clear present status
1138 if ( WriteSignature (padapter, pdev, spigot, padapter->survivor) )
1140 DEB (printk ("\n failed, write signature"));
1141 return TRUE;
1143 padapter->failinprog = TRUE;
1144 return FALSE;
1146 /****************************************************************
1147 * Name: TimerExpiry :LOCAL
1149 * Description: Timer expiry routine.
1151 * Parameters: data - Pointer adapter data structure.
1153 * Returns: Nothing.
1155 ****************************************************************/
1156 static void TimerExpiry (unsigned long data)
1158 PADAPTER2220I padapter = (PADAPTER2220I)data;
1159 struct Scsi_Host *host = padapter->SCpnt->device->host;
1160 POUR_DEVICE pdev = padapter->pdev;
1161 UCHAR status = IDE_STATUS_BUSY;
1162 UCHAR temp, temp1;
1163 unsigned long flags;
1166 * Disable interrupts, if they aren't already disabled and acquire
1167 * the I/O spinlock.
1169 spin_lock_irqsave (host->host_lock, flags);
1170 DEB (printk ("\nPCI2220I: Timeout expired "));
1172 if ( padapter->failinprog )
1174 DEB (printk ("in failover process"));
1175 OpDone (padapter, DecodeError (padapter, inb_p (padapter->regStatCmd)));
1176 goto timerExpiryDone;
1179 while ( padapter->reconPhase )
1181 DEB (printk ("in recon phase %X", padapter->reconPhase));
1182 switch ( padapter->reconPhase )
1184 case RECON_PHASE_MARKING:
1185 case RECON_PHASE_LAST:
1186 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 1 : 0;
1187 DEB (printk ("\npci2220i: FAILURE 1"));
1188 if ( InitFailover (padapter, pdev) )
1189 OpDone (padapter, DID_ERROR << 16);
1190 goto timerExpiryDone;
1192 case RECON_PHASE_READY:
1193 OpDone (padapter, DID_ERROR << 16);
1194 goto timerExpiryDone;
1196 case RECON_PHASE_COPY:
1197 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
1198 DEB (printk ("\npci2220i: FAILURE 2"));
1199 DEB (printk ("\n spig/stat = %X", inb_p (padapter->regStatSel));
1200 if ( InitFailover (padapter, pdev) )
1201 OpDone (padapter, DID_ERROR << 16);
1202 goto timerExpiryDone;
1204 case RECON_PHASE_UPDATE:
1205 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
1206 DEB (printk ("\npci2220i: FAILURE 3")));
1207 if ( InitFailover (padapter, pdev) )
1208 OpDone (padapter, DID_ERROR << 16);
1209 goto timerExpiryDone;
1211 case RECON_PHASE_END:
1212 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
1213 DEB (printk ("\npci2220i: FAILURE 4"));
1214 if ( InitFailover (padapter, pdev) )
1215 OpDone (padapter, DID_ERROR << 16);
1216 goto timerExpiryDone;
1218 default:
1219 goto timerExpiryDone;
1223 while ( padapter->cmd )
1225 outb_p (0x08, padapter->regDmaCmdStat); // cancel interrupt from DMA engine
1226 if ( pdev->raid )
1228 if ( padapter->cmd == WRITE_CMD )
1230 DEB (printk ("in RAID write operation"));
1231 temp = ( pdev->spigot & (SEL_1 | SEL_2) ) ? SEL_1 : SEL_3;
1232 if ( inb_p (padapter->regStatSel) & temp )
1234 DEB (printk ("\npci2220i: Determined A OK"));
1235 SelectSpigot (padapter, temp | SEL_IRQ_OFF); // Masking the interrupt during spigot select
1236 temp = inb_p (padapter->regStatCmd);
1238 else
1239 temp = IDE_STATUS_BUSY;
1241 temp1 = ( pdev->spigot & (SEL_1 | SEL_2) ) ? SEL_2 : SEL_4;
1242 if ( inb (padapter->regStatSel) & temp1 )
1244 DEB (printk ("\npci2220i: Determined B OK"));
1245 SelectSpigot (padapter, temp1 | SEL_IRQ_OFF); // Masking the interrupt during spigot select
1246 temp1 = inb_p (padapter->regStatCmd);
1248 else
1249 temp1 = IDE_STATUS_BUSY;
1251 if ( (temp & IDE_STATUS_BUSY) || (temp1 & IDE_STATUS_BUSY) )
1253 DEB (printk ("\npci2220i: Status A: %X B: %X", temp & 0xFF, temp1 & 0xFF));
1254 if ( (temp & IDE_STATUS_BUSY) && (temp1 & IDE_STATUS_BUSY) )
1256 status = temp;
1257 break;
1259 else
1261 if ( temp & IDE_STATUS_BUSY )
1262 padapter->survivor = 1;
1263 else
1264 padapter->survivor = 0;
1265 if ( InitFailover (padapter, pdev) )
1267 status = inb_p (padapter->regStatCmd);
1268 break;
1270 goto timerExpiryDone;
1274 else
1276 DEB (printk ("in RAID read operation"));
1277 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
1278 DEB (printk ("\npci2220i: FAILURE 6"));
1279 if ( InitFailover (padapter, pdev) )
1281 status = inb_p (padapter->regStatCmd);
1282 break;
1284 goto timerExpiryDone;
1287 else
1289 DEB (printk ("in I/O operation"));
1290 status = inb_p (padapter->regStatCmd);
1292 break;
1295 OpDone (padapter, DecodeError (padapter, status));
1297 timerExpiryDone:;
1299 * Release the I/O spinlock and restore the original flags
1300 * which will enable interrupts if and only if they were
1301 * enabled on entry.
1303 spin_unlock_irqrestore (host->host_lock, flags);
1305 /****************************************************************
1306 * Name: SetReconstruct :LOCAL
1308 * Description: Set the reconstruct up.
1310 * Parameters: pdev - Pointer to device structure.
1311 * index - Mirror index number.
1313 * Returns: Number of sectors on new disk required.
1315 ****************************************************************/
1316 static LONG SetReconstruct (POUR_DEVICE pdev, int index)
1318 pdev->DiskMirror[index].status = UCBF_MIRRORED; // setup the flags
1319 pdev->DiskMirror[index ^ 1].status = UCBF_MIRRORED | UCBF_REBUILD;
1320 pdev->DiskMirror[index ^ 1].reconstructPoint = 0; // start the reconstruct
1321 pdev->reconCount = 1990; // mark target drive early
1322 return pdev->DiskMirror[index].reconstructPoint;
1324 /****************************************************************
1325 * Name: ReconTimerExpiry :LOCAL
1327 * Description: Reconstruct timer expiry routine.
1329 * Parameters: data - Pointer adapter data structure.
1331 * Returns: Nothing.
1333 ****************************************************************/
1334 static void ReconTimerExpiry (unsigned long data)
1336 PADAPTER2220I padapter = (PADAPTER2220I)data;
1337 struct Scsi_Host *host = padapter->SCpnt->device->host;
1338 POUR_DEVICE pdev;
1339 ULONG testsize = 0;
1340 PIDENTIFY_DATA pid;
1341 USHORT minmode;
1342 ULONG zl;
1343 UCHAR zc;
1344 USHORT z;
1345 unsigned long flags;
1348 * Disable interrupts, if they aren't already disabled and acquire
1349 * the I/O spinlock.
1351 spin_lock_irqsave(host->host_lock, flags);
1353 if ( padapter->SCpnt )
1354 goto reconTimerExpiry;
1356 padapter->reconTimer.data = 0;
1357 for ( z = padapter->devInReconIndex + 1; z < BIGD_MAXDRIVES; z++ )
1359 if ( padapter->device[z].reconOn )
1360 break;
1362 if ( z < BIGD_MAXDRIVES )
1363 pdev = &padapter->device[z];
1364 else
1366 for ( z = 0; z < BIGD_MAXDRIVES; z++ )
1368 if ( padapter->device[z].reconOn )
1369 break;
1371 if ( z < BIGD_MAXDRIVES )
1372 pdev = &padapter->device[z];
1373 else
1375 padapter->reconOn = FALSE;
1376 goto reconTimerExpiry;
1380 padapter->devInReconIndex = z;
1381 pid = (PIDENTIFY_DATA)padapter->kBuffer;
1382 padapter->pdev = pdev;
1383 if ( pdev->reconIsStarting )
1385 pdev->reconIsStarting = FALSE;
1386 pdev->reconOn = FALSE;
1388 while ( (pdev->DiskMirror[0].signature == SIGNATURE) && (pdev->DiskMirror[1].signature == SIGNATURE) &&
1389 (pdev->DiskMirror[0].pairIdentifier == (pdev->DiskMirror[1].pairIdentifier ^ 1)) )
1391 if ( (pdev->DiskMirror[0].status & UCBF_MATCHED) && (pdev->DiskMirror[1].status & UCBF_MATCHED) )
1392 break;
1394 if ( pdev->DiskMirror[0].status & UCBF_SURVIVOR ) // is first drive survivor?
1395 testsize = SetReconstruct (pdev, 0);
1396 else
1397 if ( pdev->DiskMirror[1].status & UCBF_SURVIVOR ) // is second drive survivor?
1398 testsize = SetReconstruct (pdev, 1);
1400 if ( (pdev->DiskMirror[0].status & UCBF_REBUILD) || (pdev->DiskMirror[1].status & UCBF_REBUILD) )
1402 if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
1403 pdev->mirrorRecon = 0;
1404 else
1405 pdev->mirrorRecon = 1;
1406 pdev->reconOn = TRUE;
1408 break;
1411 if ( !pdev->reconOn )
1412 goto reconTimerExpiry;
1414 if ( padapter->bigD )
1416 padapter->failRegister = 0;
1417 outb_p (~padapter->failRegister, padapter->regFail);
1419 else
1421 zc = ((inb_p (padapter->regStatSel) >> 3) | inb_p (padapter->regStatSel)) & 0x83; // mute the alarm
1422 outb_p (0xFF, padapter->regFail);
1425 while ( 1 )
1427 DEB (printk ("\npci2220i: hard reset issue"));
1428 if ( HardReset (padapter, pdev, pdev->spigots[pdev->mirrorRecon]) )
1430 DEB (printk ("\npci2220i: sub 1"));
1431 break;
1434 pdev->lastsectorlba[pdev->mirrorRecon] = InlineIdentify (padapter, pdev->spigots[pdev->mirrorRecon], pdev->deviceID[pdev->mirrorRecon] & 1);
1436 if ( pdev->lastsectorlba[pdev->mirrorRecon] < testsize )
1438 DEB (printk ("\npci2220i: sub 2 %ld %ld", pdev->lastsectorlba[pdev->mirrorRecon], testsize));
1439 break;
1442 // test LBA and multiper sector transfer compatibility
1443 if (!pid->SupportLBA || (pid->NumSectorsPerInt < SECTORSXFER) || !pid->Valid_64_70 )
1445 DEB (printk ("\npci2220i: sub 3"));
1446 break;
1449 // test PIO/bus matering mode compatibility
1450 if ( (pid->MinPIOCycleWithoutFlow > 240) && !pid->SupportIORDYDisable && !padapter->timingPIO )
1452 DEB (printk ("\npci2220i: sub 4"));
1453 break;
1456 if ( pid->MinPIOCycleWithoutFlow <= 120 ) // setup timing mode of drive
1457 minmode = 5;
1458 else
1460 if ( pid->MinPIOCylceWithFlow <= 150 )
1461 minmode = 4;
1462 else
1464 if ( pid->MinPIOCylceWithFlow <= 180 )
1465 minmode = 3;
1466 else
1468 if ( pid->MinPIOCylceWithFlow <= 240 )
1469 minmode = 2;
1470 else
1472 DEB (printk ("\npci2220i: sub 5"));
1473 break;
1479 if ( padapter->timingMode > minmode ) // set minimum timing mode
1480 padapter->timingMode = minmode;
1481 if ( padapter->timingMode >= 2 )
1482 padapter->timingAddress = ModeArray[padapter->timingMode - 2];
1483 else
1484 padapter->timingPIO = TRUE;
1486 padapter->reconOn = TRUE;
1487 break;
1490 if ( !pdev->reconOn )
1492 padapter->survivor = pdev->mirrorRecon ^ 1;
1493 padapter->reconPhase = RECON_PHASE_FAILOVER;
1494 DEB (printk ("\npci2220i: FAILURE 7"));
1495 InitFailover (padapter, pdev);
1496 goto reconTimerExpiry;
1499 pdev->raid = TRUE;
1501 if ( WriteSignature (padapter, pdev, pdev->spigot, pdev->mirrorRecon ^ 1) )
1502 goto reconTimerExpiry;
1503 padapter->reconPhase = RECON_PHASE_MARKING;
1504 goto reconTimerExpiry;
1507 //**********************************
1508 // reconstruct copy starts here
1509 //**********************************
1510 if ( pdev->reconCount++ > 2000 )
1512 pdev->reconCount = 0;
1513 if ( WriteSignature (padapter, pdev, pdev->spigots[pdev->mirrorRecon], pdev->mirrorRecon) )
1515 padapter->survivor = pdev->mirrorRecon ^ 1;
1516 padapter->reconPhase = RECON_PHASE_FAILOVER;
1517 DEB (printk ("\npci2220i: FAILURE 8"));
1518 InitFailover (padapter, pdev);
1519 goto reconTimerExpiry;
1521 padapter->reconPhase = RECON_PHASE_UPDATE;
1522 goto reconTimerExpiry;
1525 zl = pdev->DiskMirror[pdev->mirrorRecon].reconstructPoint;
1526 padapter->reconSize = pdev->DiskMirror[pdev->mirrorRecon ^ 1].reconstructPoint - zl;
1527 if ( padapter->reconSize > MAX_BUS_MASTER_BLOCKS )
1528 padapter->reconSize = MAX_BUS_MASTER_BLOCKS;
1530 if ( padapter->reconSize )
1532 SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1]); // select the spigots
1533 outb_p (pdev->byte6 | ((UCHAR *)(&zl))[3], padapter->regLba24); // select the drive
1534 SelectSpigot (padapter, pdev->spigot);
1535 if ( WaitReady (padapter) )
1536 goto reconTimerExpiry;
1538 SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon]);
1539 if ( WaitReady (padapter) )
1541 padapter->survivor = pdev->mirrorRecon ^ 1;
1542 padapter->reconPhase = RECON_PHASE_FAILOVER;
1543 DEB (printk ("\npci2220i: FAILURE 9"));
1544 InitFailover (padapter, pdev);
1545 goto reconTimerExpiry;
1548 SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1]);
1549 outb_p (padapter->reconSize & 0xFF, padapter->regSectCount);
1550 outb_p (((UCHAR *)(&zl))[0], padapter->regLba0);
1551 outb_p (((UCHAR *)(&zl))[1], padapter->regLba8);
1552 outb_p (((UCHAR *)(&zl))[2], padapter->regLba16);
1553 padapter->expectingIRQ = TRUE;
1554 padapter->reconPhase = RECON_PHASE_READY;
1555 SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon]);
1556 WriteCommand (padapter, WRITE_CMD);
1557 StartTimer (padapter);
1558 SelectSpigot (padapter, pdev->spigot);
1559 WriteCommand (padapter, READ_CMD);
1560 goto reconTimerExpiry;
1563 pdev->DiskMirror[pdev->mirrorRecon].status = UCBF_MIRRORED | UCBF_MATCHED;
1564 pdev->DiskMirror[pdev->mirrorRecon ^ 1].status = UCBF_MIRRORED | UCBF_MATCHED;
1565 if ( WriteSignature (padapter, pdev, pdev->spigot, pdev->mirrorRecon ^ 1) )
1566 goto reconTimerExpiry;
1567 padapter->reconPhase = RECON_PHASE_LAST;
1569 reconTimerExpiry:;
1571 * Release the I/O spinlock and restore the original flags
1572 * which will enable interrupts if and only if they were
1573 * enabled on entry.
1575 spin_unlock_irqrestore(host->host_lock, flags);
1577 /****************************************************************
1578 * Name: Irq_Handler :LOCAL
1580 * Description: Interrupt handler.
1582 * Parameters: irq - Hardware IRQ number.
1583 * dev_id -
1584 * regs -
1586 * Returns: TRUE if drive is not ready in time.
1588 ****************************************************************/
1589 static irqreturn_t Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
1591 struct Scsi_Host *shost = NULL; // Pointer to host data block
1592 PADAPTER2220I padapter; // Pointer to adapter control structure
1593 POUR_DEVICE pdev;
1594 Scsi_Cmnd *SCpnt;
1595 UCHAR status;
1596 UCHAR status1;
1597 ATAPI_STATUS statusa;
1598 ATAPI_REASON reasona;
1599 ATAPI_ERROR errora;
1600 int z;
1601 ULONG zl;
1602 unsigned long flags;
1603 int handled = 0;
1605 // DEB (printk ("\npci2220i received interrupt\n"));
1607 for ( z = 0; z < NumAdapters; z++ ) // scan for interrupt to process
1609 if ( PsiHost[z]->irq == (UCHAR)(irq & 0xFF) )
1611 if ( inw_p (HOSTDATA(PsiHost[z])->regIrqControl) & 0x8000 )
1613 shost = PsiHost[z];
1614 break;
1619 if ( !shost )
1621 DEB (printk ("\npci2220i: not my interrupt"));
1622 goto out;
1625 handled = 1;
1626 spin_lock_irqsave(shost->host_lock, flags);
1627 padapter = HOSTDATA(shost);
1628 pdev = padapter->pdev;
1629 SCpnt = padapter->SCpnt;
1630 outb_p (0x08, padapter->regDmaCmdStat); // cancel interrupt from DMA engine
1632 if ( padapter->atapi && SCpnt )
1634 *(char *)&statusa = inb_p (padapter->regStatCmd); // read the device status
1635 *(char *)&reasona = inb_p (padapter->regSectCount); // read the device interrupt reason
1637 if ( !statusa.bsy )
1639 if ( statusa.drq ) // test for transfer phase
1641 if ( !reasona.cod ) // test for data phase
1643 z = (ULONG)inb_p (padapter->regLba8) | (ULONG)(inb_p (padapter->regLba16) << 8);
1644 if ( padapter->reqSense )
1645 insw (padapter->regData, SCpnt->sense_buffer, z / 2);
1646 else
1647 AtapiBusMaster (padapter, reasona.io, z);
1648 goto irq_return;
1650 if ( reasona.cod && !reasona.io ) // test for command packet phase
1652 if ( padapter->reqSense )
1653 AtapiRequestSense (padapter, pdev, SCpnt, TRUE);
1654 else
1655 AtapiSendCdb (padapter, pdev, padapter->atapiCdb);
1656 goto irq_return;
1659 else
1661 if ( reasona.io && statusa.drdy ) // test for status phase
1663 Atapi2Scsi (padapter, SCpnt);
1664 if ( statusa.check )
1666 *(UCHAR *)&errora = inb_p (padapter->regError); // read the device error
1667 if ( errora.senseKey )
1669 if ( padapter->reqSense || AtapiRequestSense (padapter, pdev, SCpnt, FALSE) )
1670 OpDone (padapter, DID_ERROR << 16);
1672 else
1674 if ( errora.ili || errora.abort )
1675 OpDone (padapter, DID_ERROR << 16);
1676 else
1677 OpDone (padapter, DID_OK << 16);
1680 else
1681 if ( padapter->reqSense )
1683 DEB (printk ("PCI2242I: Sense codes - %X %X %X ", ((UCHAR *)SCpnt->sense_buffer)[0], ((UCHAR *)SCpnt->sense_buffer)[12], ((UCHAR *)SCpnt->sense_buffer)[13]));
1684 OpDone (padapter, (DRIVER_SENSE << 24) | (DID_OK << 16) | 2);
1686 else
1687 OpDone (padapter, DID_OK << 16);
1691 goto irq_return;
1694 if ( !padapter->expectingIRQ || !(SCpnt || padapter->reconPhase) )
1696 DEB(printk ("\npci2220i Unsolicited interrupt\n"));
1697 STOP_HERE ();
1698 goto irq_return;
1700 padapter->expectingIRQ = 0;
1702 if ( padapter->failinprog )
1704 DEB (printk ("\npci2220i interrupt failover complete"));
1705 padapter->failinprog = FALSE;
1706 status = inb_p (padapter->regStatCmd); // read the device status
1707 if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
1709 DEB (printk ("\npci2220i: interrupt failover error from drive %X", status));
1710 padapter->cmd = 0;
1712 else
1714 DEB (printk ("\npci2220i: restarting failed opertation."));
1715 pdev->spigot = (padapter->survivor) ? pdev->spigots[1] : pdev->spigots[0];
1716 del_timer (&padapter->timer);
1717 if ( padapter->reconPhase )
1718 OpDone (padapter, DID_OK << 16);
1719 else
1720 Pci2220i_QueueCommand (SCpnt, SCpnt->scsi_done);
1721 goto irq_return;
1725 if ( padapter->reconPhase )
1727 switch ( padapter->reconPhase )
1729 case RECON_PHASE_MARKING:
1730 case RECON_PHASE_LAST:
1731 status = inb_p (padapter->regStatCmd); // read the device status
1732 del_timer (&padapter->timer);
1733 if ( padapter->reconPhase == RECON_PHASE_LAST )
1735 if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
1737 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 1 : 0;
1738 DEB (printk ("\npci2220i: FAILURE 10"));
1739 if ( InitFailover (padapter, pdev) )
1740 OpDone (padapter, DecodeError (padapter, status));
1741 goto irq_return;
1743 if ( WriteSignature (padapter, pdev, pdev->spigots[pdev->mirrorRecon], pdev->mirrorRecon) )
1745 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
1746 DEB (printk ("\npci2220i: FAILURE 11"));
1747 if ( InitFailover (padapter, pdev) )
1748 OpDone (padapter, DecodeError (padapter, status));
1749 goto irq_return;
1751 padapter->reconPhase = RECON_PHASE_END;
1752 goto irq_return;
1754 OpDone (padapter, DID_OK << 16);
1755 goto irq_return;
1757 case RECON_PHASE_READY:
1758 status = inb_p (padapter->regStatCmd); // read the device status
1759 if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
1761 del_timer (&padapter->timer);
1762 OpDone (padapter, DecodeError (padapter, status));
1763 goto irq_return;
1765 SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon]);
1766 if ( WaitDrq (padapter) )
1768 del_timer (&padapter->timer);
1769 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
1770 DEB (printk ("\npci2220i: FAILURE 12"));
1771 if ( InitFailover (padapter, pdev) )
1772 OpDone (padapter, DecodeError (padapter, status));
1773 goto irq_return;
1775 SelectSpigot (padapter, pdev->spigot | SEL_COPY | padapter->bigD);
1776 padapter->reconPhase = RECON_PHASE_COPY;
1777 padapter->expectingIRQ = TRUE;
1778 if ( padapter->timingPIO )
1780 insw (padapter->regData, padapter->kBuffer, padapter->reconSize * (BYTES_PER_SECTOR / 2));
1782 else
1784 if ( (padapter->timingMode > 3) )
1786 if ( padapter->bigD )
1787 outl (BIGD_DATA_MODE3, padapter->regDmaAddrLoc);
1788 else
1789 outl (DALE_DATA_MODE3, padapter->regDmaAddrLoc);
1791 else
1792 outl (padapter->timingAddress, padapter->regDmaAddrLoc);
1793 outl (padapter->kBufferDma, padapter->regDmaAddrPci);
1794 outl (padapter->reconSize * BYTES_PER_SECTOR, padapter->regDmaCount);
1795 outb_p (8, padapter->regDmaDesc); // read operation
1796 if ( padapter->bigD )
1797 outb_p (8, padapter->regDmaMode); // no interrupt
1798 else
1799 outb_p (1, padapter->regDmaMode); // no interrupt
1800 outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear
1802 goto irq_return;
1804 case RECON_PHASE_COPY:
1805 pdev->DiskMirror[pdev->mirrorRecon].reconstructPoint += padapter->reconSize;
1807 case RECON_PHASE_UPDATE:
1808 SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon] | SEL_IRQ_OFF);
1809 status = inb_p (padapter->regStatCmd); // read the device status
1810 del_timer (&padapter->timer);
1811 if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
1813 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
1814 DEB (printk ("\npci2220i: FAILURE 13"));
1815 DEB (printk ("\n status register = %X error = %X", status, inb_p (padapter->regError)));
1816 if ( InitFailover (padapter, pdev) )
1817 OpDone (padapter, DecodeError (padapter, status));
1818 goto irq_return;
1820 OpDone (padapter, DID_OK << 16);
1821 goto irq_return;
1823 case RECON_PHASE_END:
1824 status = inb_p (padapter->regStatCmd); // read the device status
1825 del_timer (&padapter->timer);
1826 if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
1828 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
1829 DEB (printk ("\npci2220i: FAILURE 14"));
1830 if ( InitFailover (padapter, pdev) )
1831 OpDone (padapter, DecodeError (padapter, status));
1832 goto irq_return;
1834 pdev->reconOn = 0;
1835 if ( padapter->bigD )
1837 for ( z = 0; z < padapter->numberOfDrives; z++ )
1839 if ( padapter->device[z].DiskMirror[0].status & UCBF_SURVIVOR )
1841 Alarm (padapter, padapter->device[z].deviceID[0] ^ 2);
1842 MuteAlarm (padapter);
1844 if ( padapter->device[z].DiskMirror[1].status & UCBF_SURVIVOR )
1846 Alarm (padapter, padapter->device[z].deviceID[1] ^ 2);
1847 MuteAlarm (padapter);
1851 OpDone (padapter, DID_OK << 16);
1852 goto irq_return;
1854 default:
1855 goto irq_return;
1859 switch ( padapter->cmd ) // decide how to handle the interrupt
1861 case READ_CMD:
1862 if ( padapter->sectorCount )
1864 status = inb_p (padapter->regStatCmd); // read the device status
1865 if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
1867 if ( pdev->raid )
1869 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 1 : 0;
1870 del_timer (&padapter->timer);
1871 DEB (printk ("\npci2220i: FAILURE 15"));
1872 if ( !InitFailover (padapter, pdev) )
1873 goto irq_return;
1875 break;
1877 if ( padapter->timingPIO )
1879 insw (padapter->regData, padapter->kBuffer, padapter->readCount / 2);
1880 padapter->sectorCount -= padapter->readCount / BYTES_PER_SECTOR;
1881 WalkScatGath (padapter, TRUE, padapter->readCount);
1882 if ( !padapter->sectorCount )
1884 status = 0;
1885 break;
1888 else
1890 if ( padapter->readCount )
1891 WalkScatGath (padapter, TRUE, padapter->readCount);
1892 BusMaster (padapter, 1, 1);
1894 padapter->expectingIRQ = TRUE;
1895 goto irq_return;
1897 if ( padapter->readCount && !padapter->timingPIO )
1898 WalkScatGath (padapter, TRUE, padapter->readCount);
1899 status = 0;
1900 break;
1902 case WRITE_CMD:
1903 if ( pdev->raid )
1905 SelectSpigot (padapter, pdev->spigots[0] | SEL_IRQ_OFF);
1906 status = inb_p (padapter->regStatCmd); // read the device status
1907 SelectSpigot (padapter, pdev->spigots[1] | SEL_IRQ_OFF);
1908 status1 = inb_p (padapter->regStatCmd); // read the device status
1910 else
1911 SelectSpigot (padapter, pdev->spigot | SEL_IRQ_OFF);
1912 status = inb_p (padapter->regStatCmd); // read the device status
1913 status1 = 0;
1915 if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
1917 if ( pdev->raid && !(status1 & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT)) )
1919 padapter->survivor = 1;
1920 del_timer (&padapter->timer);
1921 SelectSpigot (padapter, pdev->spigot | SEL_IRQ_OFF);
1922 DEB (printk ("\npci2220i: FAILURE 16 status = %X error = %X", status, inb_p (padapter->regError)));
1923 if ( !InitFailover (padapter, pdev) )
1924 goto irq_return;
1926 break;
1928 if ( pdev->raid )
1930 if ( status1 & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
1932 padapter->survivor = 0;
1933 del_timer (&padapter->timer);
1934 DEB (printk ("\npci2220i: FAILURE 17 status = %X error = %X", status1, inb_p (padapter->regError)));
1935 if ( !InitFailover (padapter, pdev) )
1936 goto irq_return;
1937 status = status1;
1938 break;
1940 if ( padapter->sectorCount )
1942 status = WriteDataBoth (padapter, pdev);
1943 if ( status )
1945 padapter->survivor = status >> 1;
1946 del_timer (&padapter->timer);
1947 DEB (printk ("\npci2220i: FAILURE 18"));
1948 if ( !InitFailover (padapter, pdev) )
1949 goto irq_return;
1950 SelectSpigot (padapter, pdev->spigots[status] | SEL_IRQ_OFF);
1951 status = inb_p (padapter->regStatCmd); // read the device status
1952 break;
1954 padapter->expectingIRQ = TRUE;
1955 goto irq_return;
1957 status = 0;
1958 break;
1960 if ( padapter->sectorCount )
1962 SelectSpigot (padapter, pdev->spigot | padapter->bigD);
1963 status = WriteData (padapter);
1964 if ( status )
1965 break;
1966 padapter->expectingIRQ = TRUE;
1967 goto irq_return;
1969 status = 0;
1970 break;
1972 case IDE_COMMAND_IDENTIFY:
1974 PINQUIRYDATA pinquiryData = SCpnt->request_buffer;
1975 PIDENTIFY_DATA pid = (PIDENTIFY_DATA)padapter->kBuffer;
1977 status = inb_p (padapter->regStatCmd);
1978 if ( status & IDE_STATUS_DRQ )
1980 insw (padapter->regData, pid, sizeof (IDENTIFY_DATA) >> 1);
1982 memset (pinquiryData, 0, SCpnt->request_bufflen); // Zero INQUIRY data structure.
1983 pinquiryData->DeviceType = 0;
1984 pinquiryData->Versions = 2;
1985 pinquiryData->AdditionalLength = 35 - 4;
1987 // Fill in vendor identification fields.
1988 for ( z = 0; z < 20; z += 2 )
1990 pinquiryData->VendorId[z] = ((UCHAR *)pid->ModelNumber)[z + 1];
1991 pinquiryData->VendorId[z + 1] = ((UCHAR *)pid->ModelNumber)[z];
1994 // Initialize unused portion of product id.
1995 for ( z = 0; z < 4; z++ )
1996 pinquiryData->ProductId[12 + z] = ' ';
1998 // Move firmware revision from IDENTIFY data to
1999 // product revision in INQUIRY data.
2000 for ( z = 0; z < 4; z += 2 )
2002 pinquiryData->ProductRevisionLevel[z] = ((UCHAR *)pid->FirmwareRevision)[z + 1];
2003 pinquiryData->ProductRevisionLevel[z + 1] = ((UCHAR *)pid->FirmwareRevision)[z];
2005 if ( pdev == padapter->device )
2006 *((USHORT *)(&pinquiryData->VendorSpecific)) = DEVICE_DALE_1;
2008 status = 0;
2010 break;
2013 default:
2014 status = 0;
2015 break;
2018 del_timer (&padapter->timer);
2019 if ( status )
2021 DEB (printk ("\npci2220i Interrupt handler return error"));
2022 zl = DecodeError (padapter, status);
2024 else
2025 zl = DID_OK << 16;
2027 OpDone (padapter, zl);
2028 irq_return:
2029 spin_unlock_irqrestore(shost->host_lock, flags);
2030 out:
2031 return IRQ_RETVAL(handled);
2034 /****************************************************************
2035 * Name: Pci2220i_QueueCommand
2037 * Description: Process a queued command from the SCSI manager.
2039 * Parameters: SCpnt - Pointer to SCSI command structure.
2040 * done - Pointer to done function to call.
2042 * Returns: Status code.
2044 ****************************************************************/
2045 int Pci2220i_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
2047 UCHAR *cdb = (UCHAR *)SCpnt->cmnd; // Pointer to SCSI CDB
2048 PADAPTER2220I padapter = HOSTDATA(SCpnt->device->host); // Pointer to adapter control structure
2049 POUR_DEVICE pdev = &padapter->device[SCpnt->device->id];// Pointer to device information
2050 UCHAR rc; // command return code
2051 int z;
2052 PDEVICE_RAID1 pdr;
2054 SCpnt->scsi_done = done;
2055 padapter->SCpnt = SCpnt; // Save this command data
2056 padapter->readCount = 0;
2058 if ( SCpnt->use_sg )
2060 padapter->currentSgBuffer = ((struct scatterlist *)SCpnt->request_buffer)[0].address;
2061 padapter->currentSgCount = ((struct scatterlist *)SCpnt->request_buffer)[0].length;
2063 else
2065 padapter->currentSgBuffer = SCpnt->request_buffer;
2066 padapter->currentSgCount = SCpnt->request_bufflen;
2068 padapter->nextSg = 1;
2070 if ( !done )
2072 printk("pci2220i_queuecommand: %02X: done can't be NULL\n", *cdb);
2073 return 0;
2076 if ( padapter->atapi )
2078 UCHAR zlo, zhi;
2080 DEB (printk ("\nPCI2242I: ID %d, LUN %d opcode %X ", SCpnt->device->id, SCpnt->device->lun, *cdb));
2081 padapter->pdev = pdev;
2082 if ( !pdev->byte6 || SCpnt->device->lun )
2084 OpDone (padapter, DID_BAD_TARGET << 16);
2085 return 0;
2088 padapter->atapiSpecial = FALSE;
2089 padapter->reqSense = FALSE;
2090 memset (padapter->atapiCdb, 0, 16);
2091 SelectSpigot (padapter, pdev->spigot); // select the spigot
2092 AtapiDevice (padapter, pdev->byte6); // select the drive
2093 if ( AtapiWaitReady (padapter, 100) )
2095 OpDone (padapter, DID_NO_CONNECT << 16);
2096 return 0;
2099 switch ( cdb[0] )
2101 case SCSIOP_MODE_SENSE:
2102 case SCSIOP_MODE_SELECT:
2103 Scsi2Atapi (padapter, SCpnt);
2104 z = SCpnt->request_bufflen + 4;
2105 break;
2106 case SCSIOP_READ6:
2107 case SCSIOP_WRITE6:
2108 Scsi2Atapi (padapter, SCpnt);
2109 z = SCpnt->request_bufflen;
2110 break;
2111 default:
2112 memcpy (padapter->atapiCdb, cdb, SCpnt->cmd_len);
2113 z = SCpnt->request_bufflen;
2114 break;
2116 if ( z > ATAPI_TRANSFER )
2117 z = ATAPI_TRANSFER;
2118 zlo = (UCHAR)(z & 0xFF);
2119 zhi = (UCHAR)(z >> 8);
2121 AtapiCountLo (padapter, zlo);
2122 AtapiCountHi (padapter, zhi);
2123 outb_p (0, padapter->regError);
2124 WriteCommand (padapter, IDE_COMMAND_ATAPI_PACKET);
2125 if ( pdev->cmdDrqInt )
2126 return 0;
2128 if ( AtapiWaitDrq (padapter, 500) )
2130 OpDone (padapter, DID_ERROR << 16);
2131 return 0;
2133 AtapiSendCdb (padapter, pdev, padapter->atapiCdb);
2134 return 0;
2137 if ( padapter->reconPhase )
2138 return 0;
2139 if ( padapter->reconTimer.data )
2141 del_timer (&padapter->reconTimer);
2142 padapter->reconTimer.data = 0;
2145 if ( (SCpnt->device->id >= padapter->numberOfDrives) || SCpnt->device->lun )
2147 OpDone (padapter, DID_BAD_TARGET << 16);
2148 return 0;
2151 switch ( *cdb )
2153 case SCSIOP_INQUIRY: // inquiry CDB
2155 if ( cdb[2] == SC_MY_RAID )
2157 switch ( cdb[3] )
2159 case MY_SCSI_REBUILD:
2160 for ( z = 0; z < padapter->numberOfDrives; z++ )
2162 pdev = &padapter->device[z];
2163 if ( ((pdev->DiskMirror[0].status & UCBF_SURVIVOR) && (pdev->DiskMirror[1].status & UCBF_MIRRORED)) ||
2164 ((pdev->DiskMirror[1].status & UCBF_SURVIVOR) && (pdev->DiskMirror[0].status & UCBF_MIRRORED)) )
2166 padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
2169 OpDone (padapter, DID_OK << 16);
2170 break;
2171 case MY_SCSI_ALARMMUTE:
2172 MuteAlarm (padapter);
2173 OpDone (padapter, DID_OK << 16);
2174 break;
2175 case MY_SCSI_DEMOFAIL:
2176 padapter->demoFail = TRUE;
2177 OpDone (padapter, DID_OK << 16);
2178 break;
2179 default:
2180 z = cdb[5]; // get index
2181 pdr = (PDEVICE_RAID1)SCpnt->request_buffer;
2182 if ( padapter->raidData[z] )
2184 memcpy (&pdr->DiskRaid1, padapter->raidData[z], sizeof (DISK_MIRROR));
2185 if ( padapter->raidData[z]->reconstructPoint > padapter->raidData[z ^ 2]->reconstructPoint )
2186 pdr->TotalSectors = padapter->raidData[z]->reconstructPoint;
2187 else
2188 pdr->TotalSectors = padapter->raidData[z ^ 2]->reconstructPoint;
2190 else
2191 memset (pdr, 0, sizeof (DEVICE_RAID1));
2192 OpDone (padapter, DID_OK << 16);
2193 break;
2195 return 0;
2197 padapter->cmd = IDE_COMMAND_IDENTIFY;
2198 break;
2201 case SCSIOP_TEST_UNIT_READY: // test unit ready CDB
2202 OpDone (padapter, DID_OK << 16);
2203 return 0;
2204 case SCSIOP_READ_CAPACITY: // read capctiy CDB
2206 PREAD_CAPACITY_DATA pdata = (PREAD_CAPACITY_DATA)SCpnt->request_buffer;
2208 pdata->blksiz = 0x20000;
2209 XANY2SCSI ((UCHAR *)&pdata->blks, pdev->blocks);
2210 OpDone (padapter, DID_OK << 16);
2211 return 0;
2213 case SCSIOP_VERIFY: // verify CDB
2214 padapter->startSector = XSCSI2LONG (&cdb[2]);
2215 padapter->sectorCount = (UCHAR)((USHORT)cdb[8] | ((USHORT)cdb[7] << 8));
2216 padapter->cmd = IDE_COMMAND_VERIFY;
2217 break;
2218 case SCSIOP_READ: // read10 CDB
2219 padapter->startSector = XSCSI2LONG (&cdb[2]);
2220 padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8);
2221 padapter->cmd = READ_CMD;
2222 break;
2223 case SCSIOP_READ6: // read6 CDB
2224 padapter->startSector = SCSI2LONG (&cdb[1]);
2225 padapter->sectorCount = cdb[4];
2226 padapter->cmd = READ_CMD;
2227 break;
2228 case SCSIOP_WRITE: // write10 CDB
2229 padapter->startSector = XSCSI2LONG (&cdb[2]);
2230 padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8);
2231 padapter->cmd = WRITE_CMD;
2232 break;
2233 case SCSIOP_WRITE6: // write6 CDB
2234 padapter->startSector = SCSI2LONG (&cdb[1]);
2235 padapter->sectorCount = cdb[4];
2236 padapter->cmd = WRITE_CMD;
2237 break;
2238 default:
2239 DEB (printk ("pci2220i_queuecommand: Unsupported command %02X\n", *cdb));
2240 OpDone (padapter, DID_ERROR << 16);
2241 return 0;
2244 if ( padapter->reconPhase )
2245 return 0;
2247 padapter->pdev = pdev;
2249 while ( padapter->demoFail )
2251 pdev = padapter->pdev = &padapter->device[0];
2252 padapter->demoFail = FALSE;
2253 if ( !pdev->raid ||
2254 (pdev->DiskMirror[0].status & UCBF_SURVIVOR) ||
2255 (pdev->DiskMirror[1].status & UCBF_SURVIVOR) )
2257 break;
2259 if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
2260 padapter->survivor = 1;
2261 else
2262 padapter->survivor = 0;
2263 DEB (printk ("\npci2220i: FAILURE 19"));
2264 if ( InitFailover (padapter, pdev) )
2265 break;
2266 return 0;
2269 StartTimer (padapter);
2270 if ( pdev->raid && (padapter->cmd == WRITE_CMD) )
2272 rc = IdeCmdBoth (padapter, pdev);
2273 if ( !rc )
2274 rc = WriteDataBoth (padapter, pdev);
2275 if ( rc )
2277 del_timer (&padapter->timer);
2278 padapter->expectingIRQ = 0;
2279 padapter->survivor = rc >> 1;
2280 DEB (printk ("\npci2220i: FAILURE 20"));
2281 if ( InitFailover (padapter, pdev) )
2283 OpDone (padapter, DID_ERROR << 16);
2284 return 0;
2288 else
2290 rc = IdeCmd (padapter, pdev);
2291 if ( (padapter->cmd == WRITE_CMD) && !rc )
2292 rc = WriteData (padapter);
2293 if ( rc )
2295 del_timer (&padapter->timer);
2296 padapter->expectingIRQ = 0;
2297 if ( pdev->raid )
2299 padapter->survivor = (pdev->spigot ^ 3) >> 1;
2300 DEB (printk ("\npci2220i: FAILURE 21"));
2301 if ( !InitFailover (padapter, pdev) )
2302 return 0;
2304 OpDone (padapter, DID_ERROR << 16);
2305 return 0;
2308 return 0;
2310 /****************************************************************
2311 * Name: ReadFlash
2313 * Description: Read information from controller Flash memory.
2315 * Parameters: padapter - Pointer to host interface data structure.
2316 * pdata - Pointer to data structures.
2317 * base - base address in Flash.
2318 * length - lenght of data space in bytes.
2320 * Returns: Nothing.
2322 ****************************************************************/
2323 static VOID ReadFlash (PADAPTER2220I padapter, VOID *pdata, ULONG base, ULONG length)
2325 ULONG oldremap;
2326 UCHAR olddesc;
2327 ULONG z;
2328 UCHAR *pd = (UCHAR *)pdata;
2330 oldremap = inl (padapter->regRemap); // save values to restore later
2331 olddesc = inb_p (padapter->regDesc);
2333 outl (base | 1, padapter->regRemap); // remap to Flash space as specified
2334 outb_p (0x40, padapter->regDesc); // describe remap region as 8 bit
2335 for ( z = 0; z < length; z++) // get "length" data count
2336 *pd++ = inb_p (padapter->regBase + z); // read in the data
2338 outl (oldremap, padapter->regRemap); // restore remap register values
2339 outb_p (olddesc, padapter->regDesc);
2341 /****************************************************************
2342 * Name: GetRegs
2344 * Description: Initialize the regester information.
2346 * Parameters: pshost - Pointer to SCSI host data structure.
2347 * bigd - PCI-2240I identifier
2348 * pcidev - Pointer to device data structure.
2350 * Returns: TRUE if failure to install.
2352 ****************************************************************/
2353 static USHORT GetRegs (struct Scsi_Host *pshost, BOOL bigd, struct pci_dev *pcidev)
2355 PADAPTER2220I padapter;
2356 int setirq;
2357 int z;
2358 USHORT zr, zl;
2359 UCHAR *consistent;
2360 dma_addr_t consistentDma;
2362 padapter = HOSTDATA(pshost);
2363 memset (padapter, 0, sizeof (ADAPTER2220I));
2364 memset (&DaleSetup, 0, sizeof (DaleSetup));
2365 memset (DiskMirror, 0, sizeof (DiskMirror));
2367 zr = pci_resource_start (pcidev, 1);
2368 zl = pci_resource_start (pcidev, 2);
2370 padapter->basePort = zr;
2371 padapter->regRemap = zr + RTR_LOCAL_REMAP; // 32 bit local space remap
2372 padapter->regDesc = zr + RTR_REGIONS; // 32 bit local region descriptor
2373 padapter->regRange = zr + RTR_LOCAL_RANGE; // 32 bit local range
2374 padapter->regIrqControl = zr + RTR_INT_CONTROL_STATUS; // 16 bit interrupt control and status
2375 padapter->regScratchPad = zr + RTR_MAILBOX; // 16 byte scratchpad I/O base address
2377 padapter->regBase = zl;
2378 padapter->regData = zl + REG_DATA; // data register I/O address
2379 padapter->regError = zl + REG_ERROR; // error register I/O address
2380 padapter->regSectCount = zl + REG_SECTOR_COUNT; // sector count register I/O address
2381 padapter->regLba0 = zl + REG_LBA_0; // least significant byte of LBA
2382 padapter->regLba8 = zl + REG_LBA_8; // next least significant byte of LBA
2383 padapter->regLba16 = zl + REG_LBA_16; // next most significan byte of LBA
2384 padapter->regLba24 = zl + REG_LBA_24; // head and most 4 significant bits of LBA
2385 padapter->regStatCmd = zl + REG_STAT_CMD; // status on read and command on write register
2386 padapter->regStatSel = zl + REG_STAT_SEL; // board status on read and spigot select on write register
2387 padapter->regFail = zl + REG_FAIL;
2388 padapter->regAltStat = zl + REG_ALT_STAT;
2389 padapter->pcidev = pcidev;
2391 if ( bigd )
2393 padapter->regDmaDesc = zr + RTR_DMA0_DESC_PTR; // address of the DMA discriptor register for direction of transfer
2394 padapter->regDmaCmdStat = zr + RTR_DMA_COMMAND_STATUS; // Byte #0 of DMA command status register
2395 padapter->regDmaAddrPci = zr + RTR_DMA0_PCI_ADDR; // 32 bit register for PCI address of DMA
2396 padapter->regDmaAddrLoc = zr + RTR_DMA0_LOCAL_ADDR; // 32 bit register for local bus address of DMA
2397 padapter->regDmaCount = zr + RTR_DMA0_COUNT; // 32 bit register for DMA transfer count
2398 padapter->regDmaMode = zr + RTR_DMA0_MODE + 1; // 32 bit register for DMA mode control
2399 padapter->bigD = SEL_NEW_SPEED_1; // set spigot speed control bit
2401 else
2403 padapter->regDmaDesc = zl + RTL_DMA1_DESC_PTR; // address of the DMA discriptor register for direction of transfer
2404 padapter->regDmaCmdStat = zl + RTL_DMA_COMMAND_STATUS + 1; // Byte #1 of DMA command status register
2405 padapter->regDmaAddrPci = zl + RTL_DMA1_PCI_ADDR; // 32 bit register for PCI address of DMA
2406 padapter->regDmaAddrLoc = zl + RTL_DMA1_LOCAL_ADDR; // 32 bit register for local bus address of DMA
2407 padapter->regDmaCount = zl + RTL_DMA1_COUNT; // 32 bit register for DMA transfer count
2408 padapter->regDmaMode = zl + RTL_DMA1_MODE + 1; // 32 bit register for DMA mode control
2411 padapter->numberOfDrives = inb_p (padapter->regScratchPad + BIGD_NUM_DRIVES);
2412 if ( !bigd && !padapter->numberOfDrives ) // if no devices on this board
2413 return TRUE;
2415 pshost->irq = pcidev->irq;
2416 setirq = 1;
2417 for ( z = 0; z < Installed; z++ ) // scan for shared interrupts
2419 if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses
2420 setirq = 0;
2422 if ( setirq ) // if not shared, posses
2424 if ( request_irq (pshost->irq, Irq_Handler, SA_SHIRQ, "pci2220i", padapter) < 0 )
2426 if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2220i", padapter) < 0 )
2428 printk ("Unable to allocate IRQ for PCI-2220I controller.\n");
2429 return TRUE;
2432 padapter->irqOwned = pshost->irq; // set IRQ as owned
2435 if ( padapter->numberOfDrives )
2436 consistent = pci_alloc_consistent (pcidev, SECTORSXFER * BYTES_PER_SECTOR, &consistentDma);
2437 else
2438 consistent = pci_alloc_consistent (pcidev, ATAPI_TRANSFER, &consistentDma);
2439 if ( !consistent )
2441 printk ("Unable to allocate DMA buffer for PCI-2220I controller.\n");
2442 free_irq (pshost->irq, padapter);
2443 return TRUE;
2445 padapter->kBuffer = consistent;
2446 padapter->kBufferDma = consistentDma;
2448 PsiHost[Installed] = pshost; // save SCSI_HOST pointer
2449 pshost->io_port = padapter->basePort;
2450 pshost->n_io_port = 0xFF;
2451 pshost->unique_id = padapter->regBase;
2453 outb_p (0x01, padapter->regRange); // fix our range register because other drivers want to tromp on it
2455 padapter->timingMode = inb_p (padapter->regScratchPad + DALE_TIMING_MODE);
2456 if ( padapter->timingMode >= 2 )
2458 if ( bigd )
2459 padapter->timingAddress = ModeArray2[padapter->timingMode - 2];
2460 else
2461 padapter->timingAddress = ModeArray[padapter->timingMode - 2];
2463 else
2464 padapter->timingPIO = TRUE;
2466 ReadFlash (padapter, &DaleSetup, DALE_FLASH_SETUP, sizeof (SETUP));
2467 ReadFlash (padapter, &DiskMirror, DALE_FLASH_RAID, sizeof (DiskMirror));
2469 return FALSE;
2471 /****************************************************************
2472 * Name: SetupFinish
2474 * Description: Complete the driver initialization process for a card
2476 * Parameters: padapter - Pointer to SCSI host data structure.
2477 * str - Pointer to board type string.
2479 * Returns: Nothing.
2481 ****************************************************************/
2482 VOID SetupFinish (PADAPTER2220I padapter, char *str, int irq)
2484 init_timer (&padapter->timer);
2485 padapter->timer.function = TimerExpiry;
2486 padapter->timer.data = (unsigned long)padapter;
2487 init_timer (&padapter->reconTimer);
2488 padapter->reconTimer.function = ReconTimerExpiry;
2489 padapter->reconTimer.data = (unsigned long)padapter;
2490 printk("\nPCI-%sI EIDE CONTROLLER: at I/O = %lX/%lX IRQ = %d\n", str, padapter->basePort, padapter->regBase, irq);
2491 printk("Version %s, Compiled %s %s\n\n", PCI2220I_VERSION, __DATE__, __TIME__);
2493 /****************************************************************
2494 * Name: Pci2220i_Detect
2496 * Description: Detect and initialize our boards.
2498 * Parameters: tpnt - Pointer to SCSI host template structure.
2500 * Returns: Number of adapters installed.
2502 ****************************************************************/
2503 int Pci2220i_Detect (Scsi_Host_Template *tpnt)
2505 struct Scsi_Host *pshost;
2506 PADAPTER2220I padapter;
2507 POUR_DEVICE pdev;
2508 int unit;
2509 int z;
2510 USHORT raidon;
2511 UCHAR spigot1, spigot2;
2512 UCHAR device;
2513 struct pci_dev *pcidev = NULL;
2515 while ( (pcidev = pci_find_device (VENDOR_PSI, DEVICE_DALE_1, pcidev)) != NULL )
2517 if (pci_enable_device(pcidev))
2518 continue;
2519 pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
2520 if(pshost==NULL)
2521 continue;
2523 padapter = HOSTDATA(pshost);
2525 if ( GetRegs (pshost, FALSE, pcidev) )
2526 goto unregister;
2528 scsi_set_device(pshost, &pcidev->dev);
2529 pshost->max_id = padapter->numberOfDrives;
2530 for ( z = 0; z < padapter->numberOfDrives; z++ )
2532 unit = inb_p (padapter->regScratchPad + DALE_CHANNEL_DEVICE_0 + z) & 0x0F;
2533 pdev = &padapter->device[z];
2534 pdev->byte6 = (UCHAR)(((unit & 1) << 4) | 0xE0);
2535 pdev->spigot = (UCHAR)(1 << (unit >> 1));
2536 pdev->sectors = DaleSetup.setupDevice[unit].sectors;
2537 pdev->heads = DaleSetup.setupDevice[unit].heads;
2538 pdev->cylinders = DaleSetup.setupDevice[unit].cylinders;
2539 pdev->blocks = DaleSetup.setupDevice[unit].blocks;
2541 if ( !z )
2543 DiskMirror[0].status = inb_p (padapter->regScratchPad + DALE_RAID_0_STATUS);
2544 DiskMirror[1].status = inb_p (padapter->regScratchPad + DALE_RAID_1_STATUS);
2545 if ( (DiskMirror[0].signature == SIGNATURE) && (DiskMirror[1].signature == SIGNATURE) &&
2546 (DiskMirror[0].pairIdentifier == (DiskMirror[1].pairIdentifier ^ 1)) )
2548 raidon = TRUE;
2549 if ( unit > (unit ^ 2) )
2550 unit = unit ^ 2;
2552 else
2553 raidon = FALSE;
2555 memcpy (pdev->DiskMirror, DiskMirror, sizeof (DiskMirror));
2556 padapter->raidData[0] = &pdev->DiskMirror[0];
2557 padapter->raidData[2] = &pdev->DiskMirror[1];
2559 spigot1 = spigot2 = FALSE;
2560 pdev->spigots[0] = 1;
2561 pdev->spigots[1] = 2;
2562 pdev->lastsectorlba[0] = InlineIdentify (padapter, 1, 0);
2563 pdev->lastsectorlba[1] = InlineIdentify (padapter, 2, 0);
2565 if ( !(pdev->DiskMirror[1].status & UCBF_SURVIVOR) && pdev->lastsectorlba[0] )
2566 spigot1 = TRUE;
2567 if ( !(pdev->DiskMirror[0].status & UCBF_SURVIVOR) && pdev->lastsectorlba[1] )
2568 spigot2 = TRUE;
2569 if ( pdev->DiskMirror[0].status & DiskMirror[1].status & UCBF_SURVIVOR )
2570 spigot1 = TRUE;
2572 if ( spigot1 && (pdev->DiskMirror[0].status & UCBF_REBUILD) )
2573 InlineReadSignature (padapter, pdev, 0);
2574 if ( spigot2 && (pdev->DiskMirror[1].status & UCBF_REBUILD) )
2575 InlineReadSignature (padapter, pdev, 1);
2577 if ( spigot1 && spigot2 && raidon )
2579 pdev->raid = 1;
2580 if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
2581 pdev->spigot = 2;
2582 else
2583 pdev->spigot = 1;
2584 if ( (pdev->DiskMirror[0].status & UCBF_REBUILD) || (pdev->DiskMirror[1].status & UCBF_REBUILD) )
2585 padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
2587 else
2589 if ( spigot1 )
2591 if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
2592 goto unregister;
2593 pdev->DiskMirror[0].status = UCBF_MIRRORED | UCBF_SURVIVOR;
2594 pdev->spigot = 1;
2596 else
2598 if ( pdev->DiskMirror[1].status & UCBF_REBUILD )
2599 goto unregister;
2600 pdev->DiskMirror[1].status = UCBF_MIRRORED | UCBF_SURVIVOR;
2601 pdev->spigot = 2;
2603 if ( DaleSetup.rebootRebuild && raidon )
2604 padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
2607 if ( raidon )
2608 break;
2612 SetupFinish (padapter, "2220", pshost->irq);
2614 if ( ++Installed < MAXADAPTER )
2615 continue;
2616 break;
2617 unregister:;
2618 scsi_unregister (pshost);
2621 while ( (pcidev = pci_find_device (VENDOR_PSI, DEVICE_BIGD_1, pcidev)) != NULL )
2623 pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
2624 padapter = HOSTDATA(pshost);
2626 if ( GetRegs (pshost, TRUE, pcidev) )
2627 goto unregister1;
2629 for ( z = 0; z < BIGD_MAXDRIVES; z++ )
2630 DiskMirror[z].status = inb_p (padapter->regScratchPad + BIGD_RAID_0_STATUS + z);
2632 scsi_set_pci_device(pshost, pcidev);
2633 pshost->max_id = padapter->numberOfDrives;
2634 padapter->failRegister = inb_p (padapter->regScratchPad + BIGD_ALARM_IMAGE);
2635 for ( z = 0; z < padapter->numberOfDrives; z++ )
2637 unit = inb_p (padapter->regScratchPad + BIGD_DEVICE_0 + z);
2638 pdev = &padapter->device[z];
2639 pdev->byte6 = (UCHAR)(((unit & 1) << 4) | 0xE0);
2640 pdev->spigot = (UCHAR)(1 << (unit >> 1));
2641 pdev->sectors = DaleSetup.setupDevice[unit].sectors;
2642 pdev->heads = DaleSetup.setupDevice[unit].heads;
2643 pdev->cylinders = DaleSetup.setupDevice[unit].cylinders;
2644 pdev->blocks = DaleSetup.setupDevice[unit].blocks;
2646 if ( (DiskMirror[unit].signature == SIGNATURE) && (DiskMirror[unit ^ 2].signature == SIGNATURE) &&
2647 (DiskMirror[unit].pairIdentifier == (DiskMirror[unit ^ 2].pairIdentifier ^ 1)) )
2649 raidon = TRUE;
2650 if ( unit > (unit ^ 2) )
2651 unit = unit ^ 2;
2653 else
2654 raidon = FALSE;
2656 spigot1 = spigot2 = FALSE;
2657 memcpy (&pdev->DiskMirror[0], &DiskMirror[unit], sizeof (DISK_MIRROR));
2658 memcpy (&pdev->DiskMirror[1], &DiskMirror[unit ^ 2], sizeof (DISK_MIRROR));
2659 padapter->raidData[unit] = &pdev->DiskMirror[0];
2660 padapter->raidData[unit ^ 2] = &pdev->DiskMirror[1];
2661 pdev->spigots[0] = 1 << (unit >> 1);
2662 pdev->spigots[1] = 1 << ((unit ^ 2) >> 1);
2663 pdev->deviceID[0] = unit;
2664 pdev->deviceID[1] = unit ^ 2;
2665 pdev->lastsectorlba[0] = InlineIdentify (padapter, pdev->spigots[0], unit & 1);
2666 pdev->lastsectorlba[1] = InlineIdentify (padapter, pdev->spigots[1], unit & 1);
2668 if ( !(pdev->DiskMirror[1].status & UCBF_SURVIVOR) && pdev->lastsectorlba[0] )
2669 spigot1 = TRUE;
2670 if ( !(pdev->DiskMirror[0].status & UCBF_SURVIVOR) && pdev->lastsectorlba[1] )
2671 spigot2 = TRUE;
2672 if ( pdev->DiskMirror[0].status & pdev->DiskMirror[1].status & UCBF_SURVIVOR )
2673 spigot1 = TRUE;
2675 if ( spigot1 && (pdev->DiskMirror[0].status & UCBF_REBUILD) )
2676 InlineReadSignature (padapter, pdev, 0);
2677 if ( spigot2 && (pdev->DiskMirror[1].status & UCBF_REBUILD) )
2678 InlineReadSignature (padapter, pdev, 1);
2680 if ( spigot1 && spigot2 && raidon )
2682 pdev->raid = 1;
2683 if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
2684 pdev->spigot = pdev->spigots[1];
2685 else
2686 pdev->spigot = pdev->spigots[0];
2687 if ( (pdev->DiskMirror[0].status & UCBF_REBUILD) || (pdev->DiskMirror[1].status & UCBF_REBUILD) )
2688 padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
2690 else
2692 if ( spigot1 )
2694 if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
2695 goto unregister1;
2696 pdev->DiskMirror[0].status = UCBF_MIRRORED | UCBF_SURVIVOR;
2697 pdev->spigot = pdev->spigots[0];
2699 else
2701 if ( pdev->DiskMirror[1].status & UCBF_REBUILD )
2702 goto unregister;
2703 pdev->DiskMirror[1].status = UCBF_MIRRORED | UCBF_SURVIVOR;
2704 pdev->spigot = pdev->spigots[1];
2706 if ( DaleSetup.rebootRebuild && raidon )
2707 padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
2711 if ( !padapter->numberOfDrives ) // If no ATA devices then scan ATAPI
2713 unit = 0;
2714 for ( spigot1 = 0; spigot1 < 4; spigot1++ )
2716 for ( device = 0; device < 2; device++ )
2718 DEB (printk ("\nPCI2242I: scanning for ID %d ", (spigot1 * 2) + device));
2719 pdev = &(padapter->device[(spigot1 * 2) + device]);
2720 pdev->byte6 = 0x0A | (device << 4);
2721 pdev->spigot = 1 << spigot1;
2722 if ( !AtapiReset (padapter, pdev) )
2724 DEB (printk (" Device found "));
2725 if ( !AtapiIdentify (padapter, pdev) )
2727 DEB (printk (" Device verified"));
2728 unit++;
2729 continue;
2732 pdev->spigot = pdev->byte6 = 0;
2736 if ( unit )
2738 padapter->atapi = TRUE;
2739 padapter->timingAddress = DALE_DATA_MODE3;
2740 outw_p (0x0900, padapter->regIrqControl); // Turn our interrupts on
2741 outw_p (0x0C41, padapter->regDmaMode - 1); // setup for 16 bits, ready enabled, done IRQ enabled, no incriment
2742 outb_p (0xFF, padapter->regFail); // all fail lights and alarm off
2743 pshost->max_id = 8;
2746 SetupFinish (padapter, "2240", pshost->irq);
2748 if ( ++Installed < MAXADAPTER )
2749 continue;
2750 break;
2751 unregister1:;
2752 scsi_unregister (pshost);
2755 NumAdapters = Installed;
2756 return Installed;
2758 /****************************************************************
2759 * Name: Pci2220i_Abort
2761 * Description: Process the Abort command from the SCSI manager.
2763 * Parameters: SCpnt - Pointer to SCSI command structure.
2765 * Returns: Allways snooze.
2767 ****************************************************************/
2768 int Pci2220i_Abort (Scsi_Cmnd *SCpnt)
2770 PADAPTER2220I padapter = HOSTDATA(SCpnt->device->host); // Pointer to adapter control structure
2771 POUR_DEVICE pdev = &padapter->device[SCpnt->device->id];// Pointer to device information
2773 if ( !padapter->SCpnt )
2774 return SCSI_ABORT_NOT_RUNNING;
2776 if ( padapter->atapi )
2778 if ( AtapiReset (padapter, pdev) )
2779 return SCSI_ABORT_ERROR;
2780 OpDone (padapter, DID_ABORT << 16);
2781 return SCSI_ABORT_SUCCESS;
2783 return SCSI_ABORT_SNOOZE;
2785 /****************************************************************
2786 * Name: Pci2220i_Reset
2788 * Description: Process the Reset command from the SCSI manager.
2790 * Parameters: SCpnt - Pointer to SCSI command structure.
2791 * flags - Flags about the reset command
2793 * Returns: No active command at this time, so this means
2794 * that each time we got some kind of response the
2795 * last time through. Tell the mid-level code to
2796 * request sense information in order to decide what
2797 * to do next.
2799 ****************************************************************/
2800 int Pci2220i_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
2802 PADAPTER2220I padapter = HOSTDATA(SCpnt->device->host); // Pointer to adapter control structure
2803 POUR_DEVICE pdev = &padapter->device[SCpnt->device->id];// Pointer to device information
2805 if ( padapter->atapi )
2807 if ( AtapiReset (padapter, pdev) )
2808 return SCSI_RESET_ERROR;
2809 return SCSI_RESET_SUCCESS;
2811 return SCSI_RESET_PUNT;
2813 /****************************************************************
2814 * Name: Pci2220i_Release
2816 * Description: Release resources allocated for a single each adapter.
2818 * Parameters: pshost - Pointer to SCSI command structure.
2820 * Returns: zero.
2822 ****************************************************************/
2823 int Pci2220i_Release (struct Scsi_Host *pshost)
2825 PADAPTER2220I padapter = HOSTDATA (pshost);
2826 USHORT z;
2828 if ( padapter->reconOn )
2830 padapter->reconOn = FALSE; // shut down the hot reconstruct
2831 if ( padapter->reconPhase )
2832 mdelay (300);
2833 if ( padapter->reconTimer.data ) // is the timer running?
2835 del_timer (&padapter->reconTimer);
2836 padapter->reconTimer.data = 0;
2840 // save RAID status on the board
2841 if ( padapter->bigD )
2843 outb_p (padapter->failRegister, padapter->regScratchPad + BIGD_ALARM_IMAGE);
2844 for ( z = 0; z < BIGD_MAXDRIVES; z++ )
2846 if ( padapter->raidData )
2847 outb_p (padapter->raidData[z]->status, padapter->regScratchPad + BIGD_RAID_0_STATUS + z);
2848 else
2849 outb_p (0, padapter->regScratchPad + BIGD_RAID_0_STATUS);
2852 else
2854 outb_p (padapter->device[0].DiskMirror[0].status, padapter->regScratchPad + DALE_RAID_0_STATUS);
2855 outb_p (padapter->device[0].DiskMirror[1].status, padapter->regScratchPad + DALE_RAID_1_STATUS);
2858 if ( padapter->irqOwned )
2859 free_irq (pshost->irq, padapter);
2860 release_region (pshost->io_port, pshost->n_io_port);
2861 if ( padapter->numberOfDrives )
2862 pci_free_consistent (padapter->pcidev, SECTORSXFER * BYTES_PER_SECTOR, padapter->kBuffer, padapter->kBufferDma);
2863 else
2864 pci_free_consistent (padapter->pcidev, ATAPI_TRANSFER, padapter->kBuffer, padapter->kBufferDma);
2865 scsi_unregister(pshost);
2866 return 0;
2869 /****************************************************************
2870 * Name: Pci2220i_BiosParam
2872 * Description: Process the biosparam request from the SCSI manager to
2873 * return C/H/S data.
2875 * Parameters: disk - Pointer to SCSI disk structure.
2876 * dev - Major/minor number from kernel.
2877 * geom - Pointer to integer array to place geometry data.
2879 * Returns: zero.
2881 ****************************************************************/
2882 int Pci2220i_BiosParam (struct scsi_device *sdev, struct block_device *dev,
2883 sector_t capacity, int geom[])
2885 POUR_DEVICE pdev;
2887 if ( !(HOSTDATA(sdev->host))->atapi )
2889 pdev = &(HOSTDATA(sdev->host)->device[sdev->id]);
2891 geom[0] = pdev->heads;
2892 geom[1] = pdev->sectors;
2893 geom[2] = pdev->cylinders;
2895 return 0;
2898 MODULE_LICENSE("Dual BSD/GPL");
2900 static Scsi_Host_Template driver_template = {
2901 .proc_name = "pci2220i",
2902 .name = "PCI-2220I/PCI-2240I",
2903 .detect = Pci2220i_Detect,
2904 .release = Pci2220i_Release,
2905 .queuecommand = Pci2220i_QueueCommand,
2906 .abort = Pci2220i_Abort,
2907 .reset = Pci2220i_Reset,
2908 .bios_param = Pci2220i_BiosParam,
2909 .can_queue = 1,
2910 .this_id = -1,
2911 .sg_tablesize = SG_ALL,
2912 .cmd_per_lun = 1,
2913 .use_clustering = DISABLE_CLUSTERING,
2915 #include "scsi_module.c"