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.
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
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 ****************************************************************************/
29 #include <linux/module.h>
30 #include <linux/kernel.h>
31 #include <linux/types.h>
32 #include <linux/string.h>
33 #include <linux/malloc.h>
34 #include <linux/pci.h>
35 #include <linux/ioport.h>
36 #include <linux/delay.h>
37 #include <linux/sched.h>
38 #include <linux/proc_fs.h>
39 #include <linux/stat.h>
40 #include <linux/kdev_t.h>
41 #include <linux/blk.h>
42 #include <linux/timer.h>
44 #include <asm/system.h>
50 #if LINUX_VERSION_CODE >= LINUXVERSION(2,1,95)
51 #include <linux/spinlock.h>
53 #if LINUX_VERSION_CODE < LINUXVERSION(2,1,93)
54 #include <linux/bios32.h>
57 #define PCI2220I_VERSION "1.11"
58 //#define READ_CMD IDE_COMMAND_READ
59 //#define WRITE_CMD IDE_COMMAND_WRITE
60 //#define MAX_BUS_MASTER_BLOCKS 1 // This is the maximum we can bus master
61 #define READ_CMD IDE_CMD_READ_MULTIPLE
62 #define WRITE_CMD IDE_CMD_WRITE_MULTIPLE
63 #define MAX_BUS_MASTER_BLOCKS SECTORSXFER // This is the maximum we can bus master
66 struct proc_dir_entry Proc_Scsi_Pci2220i
=
67 { PROC_SCSI_PCI2220I
, 8, "pci2220i", S_IFDIR
| S_IRUGO
| S_IXUGO
, 2 };
73 #define STOP_HERE() {int st;for(st=0;st<100;st++){st=1;}}
79 #define MAXADAPTER 4 // Increase this and the sizes of the arrays below, if you need more.
84 UCHAR device
; // device code
85 UCHAR byte6
; // device select register image
86 UCHAR spigot
; // spigot number
87 UCHAR sparebyte
; // placeholder
88 USHORT sectors
; // number of sectors per track
89 USHORT heads
; // number of heads
90 USHORT cylinders
; // number of cylinders for this device
91 USHORT spareword
; // placeholder
92 ULONG blocks
; // number of blocks on device
93 DISK_MIRROR DiskMirror
[2]; // RAID status and control
94 ULONG lastsectorlba
[2]; // last addressable sector on the drive
95 USHORT raid
; // RAID active flag
99 } OUR_DEVICE
, *POUR_DEVICE
;
103 USHORT regDmaDesc
; // address of the DMA discriptor register for direction of transfer
104 USHORT regDmaCmdStat
; // Byte #1 of DMA command status register
105 USHORT regDmaAddrPci
; // 32 bit register for PCI address of DMA
106 USHORT regDmaAddrLoc
; // 32 bit register for local bus address of DMA
107 USHORT regDmaCount
; // 32 bit register for DMA transfer count
108 USHORT regDmaMode
; // 32 bit register for DMA mode control
109 USHORT regRemap
; // 32 bit local space remap
110 USHORT regDesc
; // 32 bit local region descriptor
111 USHORT regRange
; // 32 bit local range
112 USHORT regIrqControl
; // 16 bit Interrupt enable/disable and status
113 USHORT regScratchPad
; // scratch pad I/O base address
114 USHORT regBase
; // Base I/O register for data space
115 USHORT regData
; // data register I/O address
116 USHORT regError
; // error register I/O address
117 USHORT regSectCount
; // sector count register I/O address
118 USHORT regLba0
; // least significant byte of LBA
119 USHORT regLba8
; // next least significant byte of LBA
120 USHORT regLba16
; // next most significan byte of LBA
121 USHORT regLba24
; // head and most 4 significant bits of LBA
122 USHORT regStatCmd
; // status on read and command on write register
123 USHORT regStatSel
; // board status on read and spigot select on write register
124 USHORT regFail
; // fail bits control register
125 USHORT regAltStat
; // alternate status and drive control register
126 USHORT basePort
; // PLX base I/O port
127 USHORT timingMode
; // timing mode currently set for adapter
128 USHORT timingPIO
; // TRUE if PIO timing is active
129 ULONG timingAddress
; // address to use on adapter for current timing mode
130 ULONG irqOwned
; // owned IRQ or zero if shared
131 OUR_DEVICE device
[DALE_MAXDRIVES
];
132 DISK_MIRROR
*raidData
[8];
138 POUR_DEVICE pdev
; // current device opearating on
140 USHORT reconIsStarting
; // indicate hot reconstruct is starting
141 USHORT reconOn
; // Hot reconstruct is to be done.
142 USHORT reconPhase
; // Hot reconstruct operation is in progress.
144 USHORT demoFail
; // flag for RAID failure demonstration
147 struct timer_list reconTimer
;
148 struct timer_list timer
;
150 } ADAPTER2220I
, *PADAPTER2220I
;
152 #define HOSTDATA(host) ((PADAPTER2220I)&host->hostdata)
154 #define RECON_PHASE_READY 0x01
155 #define RECON_PHASE_COPY 0x02
156 #define RECON_PHASE_UPDATE 0x03
157 #define RECON_PHASE_LAST 0x04
158 #define RECON_PHASE_END 0x07
159 #define RECON_PHASE_MARKING 0x80
160 #define RECON_PHASE_FAILOVER 0xFF
162 static struct Scsi_Host
*PsiHost
[MAXADAPTER
] = {NULL
,}; // One for each adapter
163 static int NumAdapters
= 0;
164 static SETUP DaleSetup
;
165 static DISK_MIRROR DiskMirror
[2];
166 static ULONG ModeArray
[] = {DALE_DATA_MODE2
, DALE_DATA_MODE3
, DALE_DATA_MODE4
, DALE_DATA_MODE4P
};
168 static void ReconTimerExpiry (unsigned long data
);
170 /****************************************************************
171 * Name: MuteAlarm :LOCAL
173 * Description: Mute the audible alarm.
175 * Parameters: padapter - Pointer adapter data structure.
177 * Returns: TRUE if drive does not assert DRQ in time.
179 ****************************************************************/
180 static void MuteAlarm (PADAPTER2220I padapter
)
184 old
= (inb_p (padapter
->regStatSel
) >> 3) | (inb_p (padapter
->regStatSel
) & 0x83);
185 outb_p (old
| 0x40, padapter
->regFail
);
187 /****************************************************************
188 * Name: WaitReady :LOCAL
190 * Description: Wait for device ready.
192 * Parameters: padapter - Pointer adapter data structure.
194 * Returns: TRUE if drive does not assert DRQ in time.
196 ****************************************************************/
197 static int WaitReady (PADAPTER2220I padapter
)
202 for ( z
= 0; z
< (TIMEOUT_READY
* 4); z
++ )
204 status
= inb_p (padapter
->regStatCmd
);
205 if ( (status
& (IDE_STATUS_DRDY
| IDE_STATUS_BUSY
)) == IDE_STATUS_DRDY
)
211 /****************************************************************
212 * Name: WaitReadyReset :LOCAL
214 * Description: Wait for device ready.
216 * Parameters: padapter - Pointer adapter data structure.
218 * Returns: TRUE if drive does not assert DRQ in time.
220 ****************************************************************/
221 static int WaitReadyReset (PADAPTER2220I padapter
)
226 for ( z
= 0; z
< (250 * 4); z
++ ) // wait up to 1/4 second
228 status
= inb_p (padapter
->regStatCmd
);
229 if ( (status
& (IDE_STATUS_DRDY
| IDE_STATUS_BUSY
)) == IDE_STATUS_DRDY
)
231 DEB (printk ("\nPCI2220I: Reset took %ld mSec to be ready", z
/ 4));
236 DEB (printk ("\nPCI2220I: Reset took more than 1 Second to come ready, Disk Failure"));
239 /****************************************************************
240 * Name: WaitDrq :LOCAL
242 * Description: Wait for device ready for data transfer.
244 * Parameters: padapter - Pointer adapter data structure.
246 * Returns: TRUE if drive does not assert DRQ in time.
248 ****************************************************************/
249 static int WaitDrq (PADAPTER2220I padapter
)
254 for ( z
= 0; z
< (TIMEOUT_DRQ
* 4); z
++ )
256 status
= inb_p (padapter
->regStatCmd
);
257 if ( status
& IDE_STATUS_DRQ
)
263 /****************************************************************
264 * Name: HardReset :LOCAL
266 * Description: Wait for device ready for data transfer.
268 * Parameters: padapter - Pointer adapter data structure.
269 * pdev - Pointer to device.
270 * spigot - Spigot number.
272 * Returns: TRUE if drive does not assert DRQ in time.
274 ****************************************************************/
275 static int HardReset (PADAPTER2220I padapter
, POUR_DEVICE pdev
, UCHAR spigot
)
277 SelectSpigot (padapter
, spigot
| 0x80);
279 outb_p (0x0E, padapter
->regAltStat
); // reset the suvivor
280 udelay (100); // wait a little
281 outb_p (0x08, padapter
->regAltStat
); // clear the reset
283 outb_p (0xA0, padapter
->regLba24
); //Specify drive
285 outb_p (pdev
->byte6
, padapter
->regLba24
); // select the drive
286 if ( WaitReadyReset (padapter
) )
288 outb_p (SECTORSXFER
, padapter
->regSectCount
);
289 WriteCommand (padapter
, IDE_CMD_SET_MULTIPLE
);
290 if ( WaitReady (padapter
) )
294 /****************************************************************
295 * Name: BusMaster :LOCAL
297 * Description: Do a bus master I/O.
299 * Parameters: padapter - Pointer adapter data structure.
300 * datain - TRUE if data read.
301 * irq - TRUE if bus master interrupt expected.
303 * Returns: TRUE if drive does not assert DRQ in time.
305 ****************************************************************/
306 static void BusMaster (PADAPTER2220I padapter
, UCHAR datain
, UCHAR irq
)
310 outl (padapter
->timingAddress
, padapter
->regDmaAddrLoc
);
311 outl (virt_to_bus (padapter
->buffer
), padapter
->regDmaAddrPci
);
312 zl
= (padapter
->sectorCount
> MAX_BUS_MASTER_BLOCKS
) ? MAX_BUS_MASTER_BLOCKS
: padapter
->sectorCount
;
313 padapter
->sectorCount
-= zl
;
314 zl
*= (ULONG
)BYTES_PER_SECTOR
;
315 padapter
->buffer
+= zl
;
316 outl (zl
, padapter
->regDmaCount
);
319 outb_p (8, padapter
->regDmaDesc
); // read operation
320 if ( irq
&& !padapter
->sectorCount
)
321 outb_p (5, padapter
->regDmaMode
); // interrupt on
323 outb_p (1, padapter
->regDmaMode
); // no interrupt
327 outb_p (0, padapter
->regDmaDesc
); // write operation
328 outb_p (1, padapter
->regDmaMode
); // no interrupt
330 outb_p (0x03, padapter
->regDmaCmdStat
); // kick the DMA engine in gear
332 /****************************************************************
333 * Name: WriteData :LOCAL
335 * Description: Write data to device.
337 * Parameters: padapter - Pointer adapter data structure.
339 * Returns: TRUE if drive does not assert DRQ in time.
341 ****************************************************************/
342 static int WriteData (PADAPTER2220I padapter
)
346 if ( !WaitDrq (padapter
) )
348 if ( padapter
->timingPIO
)
350 zl
= (padapter
->sectorCount
> MAX_BUS_MASTER_BLOCKS
) ? MAX_BUS_MASTER_BLOCKS
: padapter
->sectorCount
;
351 outsw (padapter
->regData
, padapter
->buffer
, zl
* (BYTES_PER_SECTOR
/ 2));
352 padapter
->sectorCount
-= zl
;
353 padapter
->buffer
+= zl
* BYTES_PER_SECTOR
;
356 BusMaster (padapter
, 0, 0);
359 padapter
->cmd
= 0; // null out the command byte
362 /****************************************************************
363 * Name: WriteDataBoth :LOCAL
365 * Description: Write data to device.
367 * Parameters: padapter - Pointer adapter data structure.
369 * Returns: TRUE if drive does not assert DRQ in time.
371 ****************************************************************/
372 static int WriteDataBoth (PADAPTER2220I padapter
)
375 UCHAR status0
, status1
;
377 SelectSpigot (padapter
, 1);
378 status0
= WaitDrq (padapter
);
381 SelectSpigot (padapter
, 2);
382 status1
= WaitDrq (padapter
);
385 SelectSpigot (padapter
, 3);
386 if ( padapter
->timingPIO
)
388 zl
= (padapter
->sectorCount
> MAX_BUS_MASTER_BLOCKS
) ? MAX_BUS_MASTER_BLOCKS
: padapter
->sectorCount
;
389 outsw (padapter
->regData
, padapter
->buffer
, zl
* (BYTES_PER_SECTOR
/ 2));
390 padapter
->sectorCount
-= zl
;
391 padapter
->buffer
+= zl
* BYTES_PER_SECTOR
;
394 BusMaster (padapter
, 0, 0);
398 padapter
->cmd
= 0; // null out the command byte
403 /****************************************************************
404 * Name: IdeCmd :LOCAL
406 * Description: Process an IDE command.
408 * Parameters: padapter - Pointer adapter data structure.
409 * pdev - Pointer to device.
411 * Returns: Zero if no error or status register contents on error.
413 ****************************************************************/
414 static UCHAR
IdeCmd (PADAPTER2220I padapter
, POUR_DEVICE pdev
)
418 SelectSpigot (padapter
, pdev
->spigot
); // select the spigot
419 outb_p (pdev
->byte6
| ((UCHAR
*)(&padapter
->startSector
))[3], padapter
->regLba24
); // select the drive
420 status
= WaitReady (padapter
);
423 outb_p (padapter
->sectorCount
, padapter
->regSectCount
);
424 outb_p (((UCHAR
*)(&padapter
->startSector
))[0], padapter
->regLba0
);
425 outb_p (((UCHAR
*)(&padapter
->startSector
))[1], padapter
->regLba8
);
426 outb_p (((UCHAR
*)(&padapter
->startSector
))[2], padapter
->regLba16
);
427 padapter
->expectingIRQ
= TRUE
;
428 WriteCommand (padapter
, padapter
->cmd
);
432 padapter
->cmd
= 0; // null out the command byte
435 /****************************************************************
436 * Name: IdeCmdBoth :LOCAL
438 * Description: Process an IDE command to both drivers.
440 * Parameters: padapter - Pointer adapter data structure.
442 * Returns: Zero if no error or spigot of error.
444 ****************************************************************/
445 static UCHAR
IdeCmdBoth (PADAPTER2220I padapter
)
450 SelectSpigot (padapter
, 3); // select the spigots
451 outb_p (padapter
->pdev
->byte6
| ((UCHAR
*)(&padapter
->startSector
))[3], padapter
->regLba24
);// select the drive
452 SelectSpigot (padapter
, 1);
453 status0
= WaitReady (padapter
);
456 SelectSpigot (padapter
, 2);
457 status1
= WaitReady (padapter
);
460 SelectSpigot (padapter
, 3);
461 outb_p (padapter
->sectorCount
, padapter
->regSectCount
);
462 outb_p (((UCHAR
*)(&padapter
->startSector
))[0], padapter
->regLba0
);
463 outb_p (((UCHAR
*)(&padapter
->startSector
))[1], padapter
->regLba8
);
464 outb_p (((UCHAR
*)(&padapter
->startSector
))[2], padapter
->regLba16
);
465 padapter
->expectingIRQ
= TRUE
;
466 WriteCommand (padapter
, padapter
->cmd
);
470 padapter
->cmd
= 0; // null out the command byte
475 /****************************************************************
476 * Name: OpDone :LOCAL
478 * Description: Complete an operatoin done sequence.
480 * Parameters: padapter - Pointer to host data block.
481 * spigot - Spigot select code.
482 * device - Device byte code.
486 ****************************************************************/
487 static void OpDone (PADAPTER2220I padapter
, ULONG result
)
489 Scsi_Cmnd
*SCpnt
= padapter
->SCpnt
;
491 if ( padapter
->reconPhase
)
493 padapter
->reconPhase
= 0;
494 if ( padapter
->SCpnt
)
496 Pci2220i_QueueCommand (SCpnt
, SCpnt
->scsi_done
);
500 if ( padapter
->reconOn
)
502 ReconTimerExpiry ((unsigned long)padapter
);
509 padapter
->SCpnt
= NULL
;
510 SCpnt
->result
= result
;
511 SCpnt
->scsi_done (SCpnt
);
512 if ( padapter
->reconOn
&& !padapter
->reconTimer
.data
)
514 padapter
->reconTimer
.expires
= jiffies
+ (HZ
/ 4); // start in 1/4 second
515 padapter
->reconTimer
.data
= (unsigned long)padapter
;
516 add_timer (&padapter
->reconTimer
);
520 /****************************************************************
521 * Name: InlineIdentify :LOCAL
523 * Description: Do an intline inquiry on a drive.
525 * Parameters: padapter - Pointer to host data block.
526 * spigot - Spigot select code.
527 * device - Device byte code.
529 * Returns: Last addressable sector or zero if none.
531 ****************************************************************/
532 static ULONG
InlineIdentify (PADAPTER2220I padapter
, UCHAR spigot
, UCHAR device
)
534 PIDENTIFY_DATA pid
= (PIDENTIFY_DATA
)padapter
->kBuffer
;
536 SelectSpigot (padapter
, spigot
| 0x80); // select the spigot
537 outb_p (device
<< 4, padapter
->regLba24
); // select the drive
538 if ( WaitReady (padapter
) )
540 WriteCommand (padapter
, IDE_COMMAND_IDENTIFY
);
541 if ( WaitDrq (padapter
) )
543 insw (padapter
->regData
, padapter
->kBuffer
, sizeof (IDENTIFY_DATA
) >> 1);
544 return (pid
->LBATotalSectors
- 1);
546 /****************************************************************
547 * Name: InlineReadSignature :LOCAL
549 * Description: Do an inline read RAID sigature.
551 * Parameters: padapter - Pointer adapter data structure.
552 * pdev - Pointer to device.
553 * index - index of data to read.
555 * Returns: Zero if no error or status register contents on error.
557 ****************************************************************/
558 static UCHAR
InlineReadSignature (PADAPTER2220I padapter
, POUR_DEVICE pdev
, int index
)
561 UCHAR spigot
= 1 << index
;
562 ULONG zl
= pdev
->lastsectorlba
[index
];
564 SelectSpigot (padapter
, spigot
| 0x80); // select the spigot without interrupts
565 outb_p (pdev
->byte6
| ((UCHAR
*)&zl
)[3], padapter
->regLba24
);
566 status
= WaitReady (padapter
);
569 outb_p (((UCHAR
*)&zl
)[2], padapter
->regLba16
);
570 outb_p (((UCHAR
*)&zl
)[1], padapter
->regLba8
);
571 outb_p (((UCHAR
*)&zl
)[0], padapter
->regLba0
);
572 outb_p (1, padapter
->regSectCount
);
573 WriteCommand (padapter
, IDE_COMMAND_READ
);
574 status
= WaitDrq (padapter
);
577 insw (padapter
->regData
, padapter
->kBuffer
, BYTES_PER_SECTOR
/ 2);
578 ((ULONG
*)(&pdev
->DiskMirror
[index
]))[0] = ((ULONG
*)(&padapter
->kBuffer
[DISK_MIRROR_POSITION
]))[0];
579 ((ULONG
*)(&pdev
->DiskMirror
[index
]))[1] = ((ULONG
*)(&padapter
->kBuffer
[DISK_MIRROR_POSITION
]))[1];
580 // some drives assert DRQ before IRQ so let's make sure we clear the IRQ
581 WaitReady (padapter
);
587 /****************************************************************
588 * Name: DecodeError :LOCAL
590 * Description: Decode and process device errors.
592 * Parameters: padapter - Pointer to adapter data.
593 * status - Status register code.
595 * Returns: The driver status code.
597 ****************************************************************/
598 static ULONG
DecodeError (PADAPTER2220I padapter
, UCHAR status
)
602 padapter
->expectingIRQ
= 0;
603 if ( status
& IDE_STATUS_WRITE_FAULT
)
605 return DID_PARITY
<< 16;
607 if ( status
& IDE_STATUS_BUSY
)
608 return DID_BUS_BUSY
<< 16;
610 error
= inb_p (padapter
->regError
);
611 DEB(printk ("\npci2220i error register: %x", error
));
615 case IDE_ERROR_TKONF
:
621 return DID_ERROR
<< 16;
623 return DID_ERROR
<< 16;
625 /****************************************************************
626 * Name: StartTimer :LOCAL
628 * Description: Start the timer.
630 * Parameters: ipadapter - Pointer adapter data structure.
634 ****************************************************************/
635 static void StartTimer (PADAPTER2220I padapter
)
637 padapter
->timer
.expires
= jiffies
+ TIMEOUT_DATA
;
638 add_timer (&padapter
->timer
);
640 /****************************************************************
641 * Name: WriteSignature :LOCAL
643 * Description: Start the timer.
645 * Parameters: padapter - Pointer adapter data structure.
646 * pdev - Pointer to our device.
647 * spigot - Selected spigot.
648 * index - index of mirror signature on device.
650 * Returns: TRUE on any error.
652 ****************************************************************/
653 static int WriteSignature (PADAPTER2220I padapter
, POUR_DEVICE pdev
, UCHAR spigot
, int index
)
657 SelectSpigot (padapter
, spigot
);
658 zl
= pdev
->lastsectorlba
[index
];
659 outb_p (pdev
->byte6
| ((UCHAR
*)&zl
)[3], padapter
->regLba24
);
660 outb_p (((UCHAR
*)&zl
)[2], padapter
->regLba16
);
661 outb_p (((UCHAR
*)&zl
)[1], padapter
->regLba8
);
662 outb_p (((UCHAR
*)&zl
)[0], padapter
->regLba0
);
663 outb_p (1, padapter
->regSectCount
);
665 WriteCommand (padapter
, IDE_COMMAND_WRITE
);
666 if ( WaitDrq (padapter
) )
668 StartTimer (padapter
);
669 padapter
->expectingIRQ
= TRUE
;
671 ((ULONG
*)(&padapter
->kBuffer
[DISK_MIRROR_POSITION
]))[0] = ((ULONG
*)(&pdev
->DiskMirror
[index
]))[0];
672 ((ULONG
*)(&padapter
->kBuffer
[DISK_MIRROR_POSITION
]))[1] = ((ULONG
*)(&pdev
->DiskMirror
[index
]))[1];
673 outsw (padapter
->regData
, padapter
->kBuffer
, BYTES_PER_SECTOR
/ 2);
676 /*******************************************************************************************************
679 * Description: This is the beginning of the failover routine
681 * Parameters: SCpnt - Pointer to SCSI command structure.
682 * padapter - Pointer adapter data structure.
683 * pdev - Pointer to our device.
685 * Returns: TRUE on error.
687 ******************************************************************************************************/
688 static int InitFailover (PADAPTER2220I padapter
, POUR_DEVICE pdev
)
692 DEB (printk ("\npci2220i: Initialize failover process - survivor = %d", padapter
->survivor
));
693 pdev
->raid
= FALSE
; //initializes system for non raid mode
695 padapter
->reconOn
= FALSE
;
696 spigot
= (padapter
->survivor
) ? 2 : 1;
698 if ( pdev
->DiskMirror
[padapter
->survivor
].status
& UCBF_REBUILD
)
701 if ( HardReset (padapter
, pdev
, spigot
) )
704 outb_p (0x3C | spigot
, padapter
->regFail
); // sound alarm and set fail light
705 pdev
->DiskMirror
[padapter
->survivor
].status
= UCBF_MIRRORED
| UCBF_SURVIVOR
; //clear present status
707 if ( WriteSignature (padapter
, pdev
, spigot
, padapter
->survivor
) )
709 padapter
->failinprog
= TRUE
;
712 /****************************************************************
713 * Name: TimerExpiry :LOCAL
715 * Description: Timer expiry routine.
717 * Parameters: data - Pointer adapter data structure.
721 ****************************************************************/
722 static void TimerExpiry (unsigned long data
)
724 PADAPTER2220I padapter
= (PADAPTER2220I
)data
;
725 POUR_DEVICE pdev
= padapter
->pdev
;
726 UCHAR status
= IDE_STATUS_BUSY
;
728 #if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
730 #else /* version >= v2.1.95 */
732 #endif /* version >= v2.1.95 */
734 #if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
735 /* Disable interrupts, if they aren't already disabled. */
738 #else /* version >= v2.1.95 */
740 * Disable interrupts, if they aren't already disabled and acquire
743 spin_lock_irqsave (&io_request_lock
, flags
);
744 #endif /* version >= v2.1.95 */
745 DEB (printk ("\nPCI2220I: Timeout expired "));
747 if ( padapter
->failinprog
)
749 DEB (printk ("in failover process"));
750 OpDone (padapter
, DecodeError (padapter
, inb_p (padapter
->regStatCmd
)));
751 goto timerExpiryDone
;
754 while ( padapter
->reconPhase
)
756 DEB (printk ("in recon phase %X", padapter
->reconPhase
));
757 switch ( padapter
->reconPhase
)
759 case RECON_PHASE_MARKING
:
760 case RECON_PHASE_LAST
:
761 padapter
->survivor
= (pdev
->spigot
^ 3) >> 1;
762 DEB (printk ("\npci2220i: FAILURE 1"));
763 if ( InitFailover (padapter
, pdev
) )
764 OpDone (padapter
, DID_ERROR
<< 16);
765 goto timerExpiryDone
;
767 case RECON_PHASE_READY
:
768 OpDone (padapter
, DID_ERROR
<< 16);
769 goto timerExpiryDone
;
771 case RECON_PHASE_COPY
:
772 padapter
->survivor
= (pdev
->spigot
) >> 1;
773 DEB (printk ("\npci2220i: FAILURE 2"));
774 DEB (printk ("\n spig/stat = %X", inb_p (padapter
->regStatSel
));
775 if ( InitFailover (padapter
, pdev
) )
776 OpDone (padapter
, DID_ERROR
<< 16);
777 goto timerExpiryDone
;
779 case RECON_PHASE_UPDATE
:
780 padapter
->survivor
= (pdev
->spigot
) >> 1;
781 DEB (printk ("\npci2220i: FAILURE 3")));
782 if ( InitFailover (padapter
, pdev
) )
783 OpDone (padapter
, DID_ERROR
<< 16);
784 goto timerExpiryDone
;
786 case RECON_PHASE_END
:
787 padapter
->survivor
= (pdev
->spigot
) >> 1;
788 DEB (printk ("\npci2220i: FAILURE 4"));
789 if ( InitFailover (padapter
, pdev
) )
790 OpDone (padapter
, DID_ERROR
<< 16);
791 goto timerExpiryDone
;
794 goto timerExpiryDone
;
798 while ( padapter
->cmd
)
800 outb_p (0x08, padapter
->regDmaCmdStat
); // cancel interrupt from DMA engine
803 if ( padapter
->cmd
== WRITE_CMD
)
805 DEB (printk ("in RAID write operation"));
806 if ( inb_p (padapter
->regStatSel
) & 1 )
808 SelectSpigot (padapter
, 0x81 ); // Masking the interrupt during spigot select
809 temp
= inb_p (padapter
->regStatCmd
);
812 temp
= IDE_STATUS_BUSY
;
814 if ( inb (padapter
->regStatSel
) & 2 )
816 SelectSpigot (padapter
, 0x82 ); // Masking the interrupt during spigot select
817 temp1
= inb_p (padapter
->regStatCmd
);
820 temp1
= IDE_STATUS_BUSY
;
822 if ( (temp
& IDE_STATUS_BUSY
) || (temp1
& IDE_STATUS_BUSY
) )
824 if ( (temp
& IDE_STATUS_BUSY
) && (temp1
& IDE_STATUS_BUSY
) )
831 if (temp
& IDE_STATUS_BUSY
)
832 padapter
->survivor
= 1;
834 padapter
->survivor
= 0;
835 DEB (printk ("\npci2220i: FAILURE 5"));
836 if ( InitFailover (padapter
, pdev
) )
838 status
= inb_p (padapter
->regStatCmd
);
841 goto timerExpiryDone
;
847 DEB (printk ("in RAID read operation"));
848 padapter
->survivor
= (pdev
->spigot
^ 3) >> 1;
849 DEB (printk ("\npci2220i: FAILURE 6"));
850 if ( InitFailover (padapter
, pdev
) )
852 status
= inb_p (padapter
->regStatCmd
);
855 goto timerExpiryDone
;
860 DEB (printk ("in I/O operation"));
861 status
= inb_p (padapter
->regStatCmd
);
866 OpDone (padapter
, DecodeError (padapter
, status
));
869 #if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
871 * Restore the original flags which will enable interrupts
872 * if and only if they were enabled on entry.
874 restore_flags (flags
);
875 #else /* version >= v2.1.95 */
877 * Release the I/O spinlock and restore the original flags
878 * which will enable interrupts if and only if they were
881 spin_unlock_irqrestore (&io_request_lock
, flags
);
882 #endif /* version >= v2.1.95 */
884 /****************************************************************
885 * Name: SetReconstruct :LOCAL
887 * Description: Set the reconstruct up.
889 * Parameters: pdev - Pointer to device structure.
890 * index - Mirror index number.
892 * Returns: Number of sectors on new disk required.
894 ****************************************************************/
895 static LONG
SetReconstruct (POUR_DEVICE pdev
, int index
)
897 pdev
->DiskMirror
[index
].status
= UCBF_MIRRORED
; // setup the flags
898 pdev
->DiskMirror
[index
^ 1].status
= UCBF_MIRRORED
| UCBF_REBUILD
;
899 pdev
->DiskMirror
[index
^ 1].reconstructPoint
= 0; // start the reconstruct
900 pdev
->reconCount
= 1990; // mark target drive early
901 pdev
->hotRecon
= 1 >> index
;
902 return pdev
->DiskMirror
[index
].reconstructPoint
;
904 /****************************************************************
905 * Name: ReconTimerExpiry :LOCAL
907 * Description: Reconstruct timer expiry routine.
909 * Parameters: data - Pointer adapter data structure.
913 ****************************************************************/
914 static void ReconTimerExpiry (unsigned long data
)
916 PADAPTER2220I padapter
;
923 #if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
925 #else /* version >= v2.1.95 */
927 #endif /* version >= v2.1.95 */
929 #if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
930 /* Disable interrupts, if they aren't already disabled. */
933 #else /* version >= v2.1.95 */
935 * Disable interrupts, if they aren't already disabled and acquire
938 spin_lock_irqsave (&io_request_lock
, flags
);
939 #endif /* version >= v2.1.95 */
941 padapter
= (PADAPTER2220I
)data
;
942 if ( padapter
->SCpnt
)
943 goto reconTimerExpiry
;
945 pdev
= padapter
->device
;
946 pid
= (PIDENTIFY_DATA
)padapter
->kBuffer
;
947 padapter
->reconTimer
.data
= 0;
948 padapter
->pdev
= pdev
;
949 if ( padapter
->reconIsStarting
)
951 padapter
->reconIsStarting
= FALSE
;
952 padapter
->reconOn
= FALSE
;
953 pdev
->hotRecon
= FALSE
;
955 if ( (pdev
->DiskMirror
[0].signature
== SIGNATURE
) && (pdev
->DiskMirror
[1].signature
== SIGNATURE
) &&
956 (pdev
->DiskMirror
[0].pairIdentifier
== (pdev
->DiskMirror
[1].pairIdentifier
^ 1)) )
958 if ( (pdev
->DiskMirror
[0].status
& UCBF_MATCHED
) && (pdev
->DiskMirror
[1].status
& UCBF_MATCHED
) )
960 goto reconTimerExpiry
;
963 if ( pdev
->DiskMirror
[0].status
& UCBF_SURVIVOR
) // is first drive survivor?
964 testsize
= SetReconstruct (pdev
, 0);
966 if ( pdev
->DiskMirror
[1].status
& UCBF_SURVIVOR
) // is second drive survivor?
967 testsize
= SetReconstruct (pdev
, 1);
969 if ( (pdev
->DiskMirror
[0].status
& UCBF_REBUILD
) || (pdev
->DiskMirror
[1].status
& UCBF_REBUILD
) )
971 if ( pdev
->DiskMirror
[0].status
& UCBF_REBUILD
)
974 pdev
->mirrorRecon
= 0;
979 pdev
->mirrorRecon
= 1;
984 if ( !pdev
->hotRecon
)
985 goto reconTimerExpiry
;
987 zc
= ((inb_p (padapter
->regStatSel
) >> 3) | inb_p (padapter
->regStatSel
)) & 0x83; // mute the alarm
988 outb_p (zc
| pdev
->hotRecon
| 0x40, padapter
->regFail
);
992 if ( HardReset (padapter
, pdev
, pdev
->hotRecon
) )
994 DEB (printk ("\npci2220i: sub 1"));
998 pdev
->lastsectorlba
[pdev
->mirrorRecon
] = InlineIdentify (padapter
, pdev
->hotRecon
, 0);
1000 if ( pdev
->lastsectorlba
[pdev
->mirrorRecon
] < testsize
)
1002 DEB (printk ("\npci2220i: sub 2 %ld %ld", pdev
->lastsectorlba
[pdev
->mirrorRecon
], testsize
));
1006 // test LBA and multiper sector transfer compatability
1007 if (!pid
->SupportLBA
|| (pid
->NumSectorsPerInt
< SECTORSXFER
) || !pid
->Valid_64_70
)
1009 DEB (printk ("\npci2220i: sub 3"));
1013 // test PIO/bus matering mode compatability
1014 if ( (pid
->MinPIOCycleWithoutFlow
> 240) && !pid
->SupportIORDYDisable
&& !padapter
->timingPIO
)
1016 DEB (printk ("\npci2220i: sub 4"));
1020 if ( pid
->MinPIOCycleWithoutFlow
<= 120 ) // setup timing mode of drive
1024 if ( pid
->MinPIOCylceWithFlow
<= 150 )
1028 if ( pid
->MinPIOCylceWithFlow
<= 180 )
1032 if ( pid
->MinPIOCylceWithFlow
<= 240 )
1036 DEB (printk ("\npci2220i: sub 5"));
1043 if ( padapter
->timingMode
> minmode
) // set minimum timing mode
1044 padapter
->timingMode
= minmode
;
1045 if ( padapter
->timingMode
>= 2 )
1046 padapter
->timingAddress
= ModeArray
[padapter
->timingMode
- 2];
1048 padapter
->timingPIO
= TRUE
;
1050 padapter
->reconOn
= TRUE
;
1054 if ( !padapter
->reconOn
)
1056 pdev
->hotRecon
= FALSE
;
1057 padapter
->survivor
= pdev
->mirrorRecon
^ 1;
1058 padapter
->reconPhase
= RECON_PHASE_FAILOVER
;
1059 DEB (printk ("\npci2220i: FAILURE 7"));
1060 InitFailover (padapter
, pdev
);
1061 goto reconTimerExpiry
;
1066 if ( WriteSignature (padapter
, pdev
, pdev
->spigot
, pdev
->mirrorRecon
^ 1) )
1067 goto reconTimerExpiry
;
1068 padapter
->reconPhase
= RECON_PHASE_MARKING
;
1069 goto reconTimerExpiry
;
1072 //**********************************
1073 // reconstruct copy starts here
1074 //**********************************
1075 if ( pdev
->reconCount
++ > 2000 )
1077 pdev
->reconCount
= 0;
1078 if ( WriteSignature (padapter
, pdev
, pdev
->hotRecon
, pdev
->mirrorRecon
) )
1080 padapter
->survivor
= pdev
->mirrorRecon
^ 1;
1081 padapter
->reconPhase
= RECON_PHASE_FAILOVER
;
1082 DEB (printk ("\npci2220i: FAILURE 8"));
1083 InitFailover (padapter
, pdev
);
1084 goto reconTimerExpiry
;
1086 padapter
->reconPhase
= RECON_PHASE_UPDATE
;
1087 goto reconTimerExpiry
;
1090 zl
= pdev
->DiskMirror
[pdev
->mirrorRecon
].reconstructPoint
;
1091 padapter
->reconSize
= pdev
->DiskMirror
[pdev
->mirrorRecon
^ 1].reconstructPoint
- zl
;
1092 if ( padapter
->reconSize
> MAX_BUS_MASTER_BLOCKS
)
1093 padapter
->reconSize
= MAX_BUS_MASTER_BLOCKS
;
1095 if ( padapter
->reconSize
)
1097 SelectSpigot (padapter
, 3); // select the spigots
1098 outb_p (pdev
->byte6
| ((UCHAR
*)(&zl
))[3], padapter
->regLba24
);// select the drive
1099 SelectSpigot (padapter
, pdev
->spigot
);
1100 if ( WaitReady (padapter
) )
1101 goto reconTimerExpiry
;
1103 SelectSpigot (padapter
, pdev
->hotRecon
);
1104 if ( WaitReady (padapter
) )
1106 padapter
->survivor
= pdev
->mirrorRecon
^ 1;
1107 padapter
->reconPhase
= RECON_PHASE_FAILOVER
;
1108 DEB (printk ("\npci2220i: FAILURE 9"));
1109 InitFailover (padapter
, pdev
);
1110 goto reconTimerExpiry
;
1113 SelectSpigot (padapter
, 3);
1114 outb_p (padapter
->reconSize
& 0xFF, padapter
->regSectCount
);
1115 outb_p (((UCHAR
*)(&zl
))[0], padapter
->regLba0
);
1116 outb_p (((UCHAR
*)(&zl
))[1], padapter
->regLba8
);
1117 outb_p (((UCHAR
*)(&zl
))[2], padapter
->regLba16
);
1118 padapter
->expectingIRQ
= TRUE
;
1119 padapter
->reconPhase
= RECON_PHASE_READY
;
1120 SelectSpigot (padapter
, pdev
->hotRecon
);
1121 WriteCommand (padapter
, WRITE_CMD
);
1122 StartTimer (padapter
);
1123 SelectSpigot (padapter
, pdev
->spigot
);
1124 WriteCommand (padapter
, READ_CMD
);
1125 goto reconTimerExpiry
;
1128 pdev
->DiskMirror
[pdev
->mirrorRecon
].status
= UCBF_MIRRORED
| UCBF_MATCHED
;
1129 pdev
->DiskMirror
[pdev
->mirrorRecon
^ 1].status
= UCBF_MIRRORED
| UCBF_MATCHED
;
1130 if ( WriteSignature (padapter
, pdev
, pdev
->spigot
, pdev
->mirrorRecon
^ 1) )
1131 goto reconTimerExpiry
;
1132 padapter
->reconPhase
= RECON_PHASE_LAST
;
1135 #if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
1137 * Restore the original flags which will enable interrupts
1138 * if and only if they were enabled on entry.
1140 restore_flags (flags
);
1141 #else /* version >= v2.1.95 */
1143 * Release the I/O spinlock and restore the original flags
1144 * which will enable interrupts if and only if they were
1147 spin_unlock_irqrestore (&io_request_lock
, flags
);
1148 #endif /* version >= v2.1.95 */
1150 /****************************************************************
1151 * Name: Irq_Handler :LOCAL
1153 * Description: Interrupt handler.
1155 * Parameters: irq - Hardware IRQ number.
1159 * Returns: TRUE if drive is not ready in time.
1161 ****************************************************************/
1162 static void Irq_Handler (int irq
, void *dev_id
, struct pt_regs
*regs
)
1164 struct Scsi_Host
*shost
= NULL
; // Pointer to host data block
1165 PADAPTER2220I padapter
; // Pointer to adapter control structure
1172 #if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
1174 #else /* version >= v2.1.95 */
1175 unsigned long flags
;
1176 #endif /* version >= v2.1.95 */
1178 #if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
1179 /* Disable interrupts, if they aren't already disabled. */
1182 #else /* version >= v2.1.95 */
1184 * Disable interrupts, if they aren't already disabled and acquire
1187 spin_lock_irqsave (&io_request_lock
, flags
);
1188 #endif /* version >= v2.1.95 */
1190 // DEB (printk ("\npci2220i recieved interrupt\n"));
1192 for ( z
= 0; z
< NumAdapters
; z
++ ) // scan for interrupt to process
1194 if ( PsiHost
[z
]->irq
== (UCHAR
)(irq
& 0xFF) )
1196 if ( inw_p (HOSTDATA(PsiHost
[z
])->regIrqControl
) & 0x8000 )
1206 DEB (printk ("\npci2220i: not my interrupt"));
1210 padapter
= HOSTDATA(shost
);
1211 pdev
= padapter
->pdev
;
1212 SCpnt
= padapter
->SCpnt
;
1214 if ( !padapter
->expectingIRQ
|| !(SCpnt
|| padapter
->reconPhase
) )
1216 DEB(printk ("\npci2220i Unsolicited interrupt\n"));
1220 padapter
->expectingIRQ
= 0;
1221 outb_p (0x08, padapter
->regDmaCmdStat
); // cancel interrupt from DMA engine
1223 if ( padapter
->failinprog
)
1225 DEB (printk ("\npci2220i interrupt failover complete"));
1226 padapter
->failinprog
= FALSE
;
1227 status
= inb_p (padapter
->regStatCmd
); // read the device status
1228 if ( status
& (IDE_STATUS_ERROR
| IDE_STATUS_WRITE_FAULT
) )
1230 DEB (printk ("\npci2220i: interrupt failover error from drive %X", status
));
1235 DEB (printk ("\npci2220i: restarting failed opertation."));
1236 pdev
->spigot
= (padapter
->survivor
) ? 2 : 1;
1237 del_timer (&padapter
->timer
);
1238 if ( padapter
->reconPhase
)
1239 OpDone (padapter
, DID_OK
<< 16);
1241 Pci2220i_QueueCommand (SCpnt
, SCpnt
->scsi_done
);
1246 if ( padapter
->reconPhase
)
1248 switch ( padapter
->reconPhase
)
1250 case RECON_PHASE_MARKING
:
1251 case RECON_PHASE_LAST
:
1252 status
= inb_p (padapter
->regStatCmd
); // read the device status
1253 del_timer (&padapter
->timer
);
1254 if ( padapter
->reconPhase
== RECON_PHASE_LAST
)
1256 if ( status
& (IDE_STATUS_ERROR
| IDE_STATUS_WRITE_FAULT
) )
1258 padapter
->survivor
= (pdev
->spigot
^ 3) >> 1;
1259 DEB (printk ("\npci2220i: FAILURE 10"));
1260 if ( InitFailover (padapter
, pdev
) )
1261 OpDone (padapter
, DecodeError (padapter
, status
));
1264 if ( WriteSignature (padapter
, pdev
, pdev
->hotRecon
, pdev
->mirrorRecon
) )
1266 padapter
->survivor
= (pdev
->spigot
) >> 1;
1267 DEB (printk ("\npci2220i: FAILURE 11"));
1268 if ( InitFailover (padapter
, pdev
) )
1269 OpDone (padapter
, DecodeError (padapter
, status
));
1272 padapter
->reconPhase
= RECON_PHASE_END
;
1275 OpDone (padapter
, DID_OK
<< 16);
1278 case RECON_PHASE_READY
:
1279 status
= inb_p (padapter
->regStatCmd
); // read the device status
1280 if ( status
& (IDE_STATUS_ERROR
| IDE_STATUS_WRITE_FAULT
) )
1282 del_timer (&padapter
->timer
);
1283 OpDone (padapter
, DecodeError (padapter
, status
));
1286 SelectSpigot (padapter
, pdev
->hotRecon
);
1287 if ( WaitDrq (padapter
) )
1289 del_timer (&padapter
->timer
);
1290 padapter
->survivor
= (pdev
->spigot
) >> 1;
1291 DEB (printk ("\npci2220i: FAILURE 12"));
1292 if ( InitFailover (padapter
, pdev
) )
1293 OpDone (padapter
, DecodeError (padapter
, status
));
1296 SelectSpigot (padapter
, pdev
->spigot
| 0x40);
1297 padapter
->reconPhase
= RECON_PHASE_COPY
;
1298 padapter
->expectingIRQ
= TRUE
;
1299 if ( padapter
->timingPIO
)
1301 insw (padapter
->regData
, padapter
->kBuffer
, padapter
->reconSize
* (BYTES_PER_SECTOR
/ 2));
1305 outl (padapter
->timingAddress
, padapter
->regDmaAddrLoc
);
1306 outl (virt_to_bus (padapter
->kBuffer
), padapter
->regDmaAddrPci
);
1307 outl (padapter
->reconSize
* BYTES_PER_SECTOR
, padapter
->regDmaCount
);
1308 outb_p (8, padapter
->regDmaDesc
); // read operation
1309 outb_p (1, padapter
->regDmaMode
); // no interrupt
1310 outb_p (0x03, padapter
->regDmaCmdStat
); // kick the DMA engine in gear
1314 case RECON_PHASE_COPY
:
1315 pdev
->DiskMirror
[pdev
->mirrorRecon
].reconstructPoint
+= padapter
->reconSize
;
1317 case RECON_PHASE_UPDATE
:
1318 SelectSpigot (padapter
, pdev
->hotRecon
| 0x80);
1319 status
= inb_p (padapter
->regStatCmd
); // read the device status
1320 del_timer (&padapter
->timer
);
1321 if ( status
& (IDE_STATUS_ERROR
| IDE_STATUS_WRITE_FAULT
) )
1323 padapter
->survivor
= (pdev
->spigot
) >> 1;
1324 DEB (printk ("\npci2220i: FAILURE 13"));
1325 if ( InitFailover (padapter
, pdev
) )
1326 OpDone (padapter
, DecodeError (padapter
, status
));
1329 OpDone (padapter
, DID_OK
<< 16);
1332 case RECON_PHASE_END
:
1333 status
= inb_p (padapter
->regStatCmd
); // read the device status
1334 del_timer (&padapter
->timer
);
1335 if ( status
& (IDE_STATUS_ERROR
| IDE_STATUS_WRITE_FAULT
) )
1337 padapter
->survivor
= (pdev
->spigot
) >> 1;
1338 DEB (printk ("\npci2220i: FAILURE 14"));
1339 if ( InitFailover (padapter
, pdev
) )
1340 OpDone (padapter
, DecodeError (padapter
, status
));
1343 padapter
->reconOn
= FALSE
;
1345 OpDone (padapter
, DID_OK
<< 16);
1353 switch ( padapter
->cmd
) // decide how to handle the interrupt
1356 if ( padapter
->sectorCount
)
1358 status
= inb_p (padapter
->regStatCmd
); // read the device status
1359 if ( status
& (IDE_STATUS_ERROR
| IDE_STATUS_WRITE_FAULT
) )
1363 padapter
->survivor
= (pdev
->spigot
^ 3) >> 1;
1364 del_timer (&padapter
->timer
);
1365 DEB (printk ("\npci2220i: FAILURE 15"));
1366 if ( !InitFailover (padapter
, pdev
) )
1371 if ( padapter
->timingPIO
)
1373 zl
= (padapter
->sectorCount
> MAX_BUS_MASTER_BLOCKS
) ? MAX_BUS_MASTER_BLOCKS
: padapter
->sectorCount
;
1374 insw (padapter
->regData
, padapter
->buffer
, zl
* (BYTES_PER_SECTOR
/ 2));
1375 padapter
->sectorCount
-= zl
;
1376 padapter
->buffer
+= zl
* BYTES_PER_SECTOR
;
1377 if ( !padapter
->sectorCount
)
1384 BusMaster (padapter
, 1, 1);
1385 padapter
->expectingIRQ
= TRUE
;
1392 SelectSpigot (padapter
, pdev
->spigot
| 0x80);
1393 status
= inb_p (padapter
->regStatCmd
); // read the device status
1396 SelectSpigot (padapter
, (pdev
->spigot
^ 3) | 0x80);
1397 status1
= inb_p (padapter
->regStatCmd
); // read the device status
1402 if ( status
& (IDE_STATUS_ERROR
| IDE_STATUS_WRITE_FAULT
) )
1404 if ( pdev
->raid
&& !(status1
& (IDE_STATUS_ERROR
| IDE_STATUS_WRITE_FAULT
)) )
1406 padapter
->survivor
= (pdev
->spigot
^ 3) >> 1;
1407 del_timer (&padapter
->timer
);
1408 SelectSpigot (padapter
, pdev
->spigot
| 0x80);
1409 DEB (printk ("\npci2220i: FAILURE 16 status = %X error = %X", status
, inb_p (padapter
->regError
)));
1410 if ( !InitFailover (padapter
, pdev
) )
1417 if ( status1
& (IDE_STATUS_ERROR
| IDE_STATUS_WRITE_FAULT
) )
1419 padapter
->survivor
= pdev
->spigot
>> 1;
1420 del_timer (&padapter
->timer
);
1421 DEB (printk ("\npci2220i: FAILURE 17 status = %X error = %X", status1
, inb_p (padapter
->regError
)));
1422 if ( !InitFailover (padapter
, pdev
) )
1427 if ( padapter
->sectorCount
)
1429 status
= WriteDataBoth (padapter
);
1432 padapter
->survivor
= (status
^ 3) >> 1;
1433 del_timer (&padapter
->timer
);
1434 DEB (printk ("\npci2220i: FAILURE 18"));
1435 if ( !InitFailover (padapter
, pdev
) )
1437 SelectSpigot (padapter
, status
| 0x80);
1438 status
= inb_p (padapter
->regStatCmd
); // read the device status
1441 padapter
->expectingIRQ
= TRUE
;
1447 if ( padapter
->sectorCount
)
1449 SelectSpigot (padapter
, pdev
->spigot
);
1450 status
= WriteData (padapter
);
1453 padapter
->expectingIRQ
= TRUE
;
1459 case IDE_COMMAND_IDENTIFY
:
1461 PINQUIRYDATA pinquiryData
= SCpnt
->request_buffer
;
1462 PIDENTIFY_DATA pid
= (PIDENTIFY_DATA
)padapter
->kBuffer
;
1464 status
= inb_p (padapter
->regStatCmd
);
1465 if ( status
& IDE_STATUS_DRQ
)
1467 insw (padapter
->regData
, pid
, sizeof (IDENTIFY_DATA
) >> 1);
1469 memset (pinquiryData
, 0, SCpnt
->request_bufflen
); // Zero INQUIRY data structure.
1470 pinquiryData
->DeviceType
= 0;
1471 pinquiryData
->Versions
= 2;
1472 pinquiryData
->AdditionalLength
= 35 - 4;
1474 // Fill in vendor identification fields.
1475 for ( z
= 0; z
< 20; z
+= 2 )
1477 pinquiryData
->VendorId
[z
] = ((UCHAR
*)pid
->ModelNumber
)[z
+ 1];
1478 pinquiryData
->VendorId
[z
+ 1] = ((UCHAR
*)pid
->ModelNumber
)[z
];
1481 // Initialize unused portion of product id.
1482 for ( z
= 0; z
< 4; z
++ )
1483 pinquiryData
->ProductId
[12 + z
] = ' ';
1485 // Move firmware revision from IDENTIFY data to
1486 // product revision in INQUIRY data.
1487 for ( z
= 0; z
< 4; z
+= 2 )
1489 pinquiryData
->ProductRevisionLevel
[z
] = ((UCHAR
*)pid
->FirmwareRevision
)[z
+ 1];
1490 pinquiryData
->ProductRevisionLevel
[z
+ 1] = ((UCHAR
*)pid
->FirmwareRevision
)[z
];
1492 if ( pdev
== padapter
->device
)
1493 *((USHORT
*)(&pinquiryData
->VendorSpecific
)) = DEVICE_DALE_1
;
1505 del_timer (&padapter
->timer
);
1508 DEB (printk ("\npci2220i Interupt hanlder return error"));
1509 zl
= DecodeError (padapter
, status
);
1514 OpDone (padapter
, zl
);
1516 #if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
1518 * Restore the original flags which will enable interrupts
1519 * if and only if they were enabled on entry.
1521 restore_flags (flags
);
1522 #else /* version >= v2.1.95 */
1524 * Release the I/O spinlock and restore the original flags
1525 * which will enable interrupts if and only if they were
1528 spin_unlock_irqrestore (&io_request_lock
, flags
);
1529 #endif /* version >= v2.1.95 */
1531 /****************************************************************
1532 * Name: Pci2220i_QueueCommand
1534 * Description: Process a queued command from the SCSI manager.
1536 * Parameters: SCpnt - Pointer to SCSI command structure.
1537 * done - Pointer to done function to call.
1539 * Returns: Status code.
1541 ****************************************************************/
1542 int Pci2220i_QueueCommand (Scsi_Cmnd
*SCpnt
, void (*done
)(Scsi_Cmnd
*))
1544 UCHAR
*cdb
= (UCHAR
*)SCpnt
->cmnd
; // Pointer to SCSI CDB
1545 PADAPTER2220I padapter
= HOSTDATA(SCpnt
->host
); // Pointer to adapter control structure
1546 POUR_DEVICE pdev
= &padapter
->device
[SCpnt
->target
];// Pointer to device information
1547 UCHAR rc
; // command return code
1551 SCpnt
->scsi_done
= done
;
1552 padapter
->buffer
= SCpnt
->request_buffer
;
1553 padapter
->SCpnt
= SCpnt
; // Save this command data
1556 printk("pci2220i_queuecommand: %02X: done can't be NULL\n", *cdb
);
1560 if ( padapter
->reconPhase
)
1562 if ( padapter
->reconTimer
.data
)
1564 del_timer (&padapter
->reconTimer
);
1565 padapter
->reconTimer
.data
= 0;
1568 if ( !pdev
->device
|| SCpnt
->lun
)
1570 OpDone (padapter
, DID_BAD_TARGET
<< 16);
1577 case SCSIOP_INQUIRY
: // inquiry CDB
1579 if ( cdb
[2] == SC_MY_RAID
)
1583 case MY_SCSI_REBUILD
:
1584 padapter
->reconOn
= padapter
->reconIsStarting
= TRUE
;
1585 OpDone (padapter
, DID_OK
<< 16);
1587 case MY_SCSI_ALARMMUTE
:
1588 MuteAlarm (padapter
);
1589 OpDone (padapter
, DID_OK
<< 16);
1591 case MY_SCSI_DEMOFAIL
:
1592 padapter
->demoFail
= TRUE
;
1593 OpDone (padapter
, DID_OK
<< 16);
1596 z
= cdb
[5]; // get index
1597 pdr
= (PDEVICE_RAID1
)SCpnt
->request_buffer
;
1598 if ( padapter
->raidData
[z
] )
1600 memcpy (&pdr
->DiskRaid1
, padapter
->raidData
[z
], sizeof (DISK_MIRROR
));
1601 pdr
->TotalSectors
= padapter
->device
[0].blocks
;
1604 memset (pdr
, 0, sizeof (DEVICE_RAID1
));
1605 OpDone (padapter
, DID_OK
<< 16);
1610 padapter
->cmd
= IDE_COMMAND_IDENTIFY
;
1614 case SCSIOP_TEST_UNIT_READY
: // test unit ready CDB
1615 OpDone (padapter
, DID_OK
<< 16);
1617 case SCSIOP_READ_CAPACITY
: // read capctiy CDB
1619 PREAD_CAPACITY_DATA pdata
= (PREAD_CAPACITY_DATA
)SCpnt
->request_buffer
;
1621 pdata
->blksiz
= 0x20000;
1622 XANY2SCSI ((UCHAR
*)&pdata
->blks
, pdev
->blocks
);
1623 OpDone (padapter
, DID_OK
<< 16);
1626 case SCSIOP_VERIFY
: // verify CDB
1627 padapter
->startSector
= XSCSI2LONG (&cdb
[2]);
1628 padapter
->sectorCount
= (UCHAR
)((USHORT
)cdb
[8] | ((USHORT
)cdb
[7] << 8));
1629 padapter
->cmd
= IDE_COMMAND_VERIFY
;
1631 case SCSIOP_READ
: // read10 CDB
1632 padapter
->startSector
= XSCSI2LONG (&cdb
[2]);
1633 padapter
->sectorCount
= (USHORT
)cdb
[8] | ((USHORT
)cdb
[7] << 8);
1634 padapter
->cmd
= READ_CMD
;
1636 case SCSIOP_READ6
: // read6 CDB
1637 padapter
->startSector
= SCSI2LONG (&cdb
[1]);
1638 padapter
->sectorCount
= cdb
[4];
1639 padapter
->cmd
= READ_CMD
;
1641 case SCSIOP_WRITE
: // write10 CDB
1642 padapter
->startSector
= XSCSI2LONG (&cdb
[2]);
1643 padapter
->sectorCount
= (USHORT
)cdb
[8] | ((USHORT
)cdb
[7] << 8);
1644 padapter
->cmd
= WRITE_CMD
;
1646 case SCSIOP_WRITE6
: // write6 CDB
1647 padapter
->startSector
= SCSI2LONG (&cdb
[1]);
1648 padapter
->sectorCount
= cdb
[4];
1649 padapter
->cmd
= WRITE_CMD
;
1652 DEB (printk ("pci2220i_queuecommand: Unsupported command %02X\n", *cdb
));
1653 OpDone (padapter
, DID_ERROR
<< 16);
1657 if ( padapter
->reconPhase
)
1660 padapter
->pdev
= pdev
;
1662 while ( padapter
->demoFail
)
1664 padapter
->demoFail
= FALSE
;
1666 (pdev
->DiskMirror
[0].status
& UCBF_SURVIVOR
) ||
1667 (pdev
->DiskMirror
[1].status
& UCBF_SURVIVOR
) )
1671 if ( pdev
->DiskMirror
[0].status
& UCBF_REBUILD
)
1672 padapter
->survivor
= 1;
1674 padapter
->survivor
= 0;
1675 DEB (printk ("\npci2220i: FAILURE 19"));
1676 if ( InitFailover (padapter
, pdev
) )
1681 StartTimer (padapter
);
1682 if ( pdev
->raid
&& (padapter
->cmd
== WRITE_CMD
) )
1684 rc
= IdeCmdBoth (padapter
);
1686 rc
= WriteDataBoth (padapter
);
1689 del_timer (&padapter
->timer
);
1690 padapter
->expectingIRQ
= 0;
1691 padapter
->survivor
= (rc
^ 3) >> 1;
1692 DEB (printk ("\npci2220i: FAILURE 20"));
1693 if ( InitFailover (padapter
, pdev
) )
1695 OpDone (padapter
, DID_ERROR
<< 16);
1702 rc
= IdeCmd (padapter
, pdev
);
1703 if ( (padapter
->cmd
== WRITE_CMD
) && !rc
)
1704 rc
= WriteData (padapter
);
1707 del_timer (&padapter
->timer
);
1708 padapter
->expectingIRQ
= 0;
1711 padapter
->survivor
= (pdev
->spigot
^ 3) >> 1;
1712 DEB (printk ("\npci2220i: FAILURE 21"));
1713 if ( !InitFailover (padapter
, pdev
) )
1716 OpDone (padapter
, DID_ERROR
<< 16);
1723 static void internal_done(Scsi_Cmnd
*SCpnt
)
1725 SCpnt
->SCp
.Status
++;
1727 /****************************************************************
1728 * Name: Pci2220i_Command
1730 * Description: Process a command from the SCSI manager.
1732 * Parameters: SCpnt - Pointer to SCSI command structure.
1734 * Returns: Status code.
1736 ****************************************************************/
1737 int Pci2220i_Command (Scsi_Cmnd
*SCpnt
)
1739 Pci2220i_QueueCommand (SCpnt
, internal_done
);
1740 SCpnt
->SCp
.Status
= 0;
1741 while (!SCpnt
->SCp
.Status
)
1743 return SCpnt
->result
;
1745 /****************************************************************
1748 * Description: Read information from controller Flash memory.
1750 * Parameters: padapter - Pointer to host interface data structure.
1751 * pdata - Pointer to data structures.
1752 * base - base address in Flash.
1753 * length - lenght of data space in bytes.
1757 ****************************************************************/
1758 VOID
ReadFlash (PADAPTER2220I padapter
, VOID
*pdata
, ULONG base
, ULONG length
)
1763 UCHAR
*pd
= (UCHAR
*)pdata
;
1765 oldremap
= inl (padapter
->regRemap
); // save values to restore later
1766 olddesc
= inb_p (padapter
->regDesc
);
1768 outl (base
| 1, padapter
->regRemap
); // remap to Flash space as specified
1769 outb_p (0x40, padapter
->regDesc
); // describe remap region as 8 bit
1770 for ( z
= 0; z
< length
; z
++) // get "length" data count
1771 *pd
++ = inb_p (padapter
->regBase
+ z
); // read in the data
1773 outl (oldremap
, padapter
->regRemap
); // restore remap register values
1774 outb_p (olddesc
, padapter
->regDesc
);
1776 /****************************************************************
1777 * Name: Pci2220i_Detect
1779 * Description: Detect and initialize our boards.
1781 * Parameters: tpnt - Pointer to SCSI host template structure.
1783 * Returns: Number of adapters installed.
1785 ****************************************************************/
1786 int Pci2220i_Detect (Scsi_Host_Template
*tpnt
)
1790 struct Scsi_Host
*pshost
;
1791 PADAPTER2220I padapter
;
1795 USHORT raidon
= FALSE
;
1797 UCHAR spigot1
= FALSE
;
1798 UCHAR spigot2
= FALSE
;
1799 #if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
1800 struct pci_dev
*pdev
= NULL
;
1802 UCHAR pci_bus
, pci_device_fn
;
1805 #if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
1806 if ( !pci_present () )
1808 if ( !pcibios_present () )
1811 printk ("pci2220i: PCI BIOS not present\n");
1815 #if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
1816 while ( (pdev
= pci_find_device (VENDOR_PSI
, DEVICE_DALE_1
, pdev
)) != NULL
)
1818 while ( !pcibios_find_device (VENDOR_PSI
, DEVICE_DALE_1
, found
, &pci_bus
, &pci_device_fn
) )
1821 pshost
= scsi_register (tpnt
, sizeof(ADAPTER2220I
));
1822 padapter
= HOSTDATA(pshost
);
1823 memset (padapter
, 0, sizeof (ADAPTER2220I
));
1825 zs
= pdev
->resource
[1].start
;
1826 padapter
->basePort
= zs
;
1827 padapter
->regRemap
= zs
+ RTR_LOCAL_REMAP
; // 32 bit local space remap
1828 padapter
->regDesc
= zs
+ RTR_REGIONS
; // 32 bit local region descriptor
1829 padapter
->regRange
= zs
+ RTR_LOCAL_RANGE
; // 32 bit local range
1830 padapter
->regIrqControl
= zs
+ RTR_INT_CONTROL_STATUS
; // 16 bit interupt control and status
1831 padapter
->regScratchPad
= zs
+ RTR_MAILBOX
; // 16 byte scratchpad I/O base address
1833 zs
= pdev
->resource
[2].start
;
1834 padapter
->regBase
= zs
;
1835 padapter
->regData
= zs
+ REG_DATA
; // data register I/O address
1836 padapter
->regError
= zs
+ REG_ERROR
; // error register I/O address
1837 padapter
->regSectCount
= zs
+ REG_SECTOR_COUNT
; // sector count register I/O address
1838 padapter
->regLba0
= zs
+ REG_LBA_0
; // least significant byte of LBA
1839 padapter
->regLba8
= zs
+ REG_LBA_8
; // next least significant byte of LBA
1840 padapter
->regLba16
= zs
+ REG_LBA_16
; // next most significan byte of LBA
1841 padapter
->regLba24
= zs
+ REG_LBA_24
; // head and most 4 significant bits of LBA
1842 padapter
->regStatCmd
= zs
+ REG_STAT_CMD
; // status on read and command on write register
1843 padapter
->regStatSel
= zs
+ REG_STAT_SEL
; // board status on read and spigot select on write register
1844 padapter
->regFail
= zs
+ REG_FAIL
;
1845 padapter
->regAltStat
= zs
+ REG_ALT_STAT
;
1847 padapter
->regDmaDesc
= zs
+ RTL_DMA1_DESC_PTR
; // address of the DMA discriptor register for direction of transfer
1848 padapter
->regDmaCmdStat
= zs
+ RTL_DMA_COMMAND_STATUS
+ 1; // Byte #1 of DMA command status register
1849 padapter
->regDmaAddrPci
= zs
+ RTL_DMA1_PCI_ADDR
; // 32 bit register for PCI address of DMA
1850 padapter
->regDmaAddrLoc
= zs
+ RTL_DMA1_LOCAL_ADDR
; // 32 bit register for local bus address of DMA
1851 padapter
->regDmaCount
= zs
+ RTL_DMA1_COUNT
; // 32 bit register for DMA transfer count
1852 padapter
->regDmaMode
= zs
+ RTL_DMA1_MODE
+ 1; // 32 bit register for DMA mode control
1854 if ( !inb_p (padapter
->regScratchPad
+ DALE_NUM_DRIVES
) ) // if no devices on this board
1857 #if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
1858 pshost
->irq
= pdev
->irq
;
1860 pcibios_read_config_byte (pci_bus
, pci_device_fn
, PCI_INTERRUPT_LINE
, &pshost
->irq
);
1863 for ( z
= 0; z
< installed
; z
++ ) // scan for shared interrupts
1865 if ( PsiHost
[z
]->irq
== pshost
->irq
) // if shared then, don't posses
1868 if ( setirq
) // if not shared, posses
1870 if ( request_irq (pshost
->irq
, Irq_Handler
, SA_SHIRQ
, "pci2220i", padapter
) < 0 )
1872 if ( request_irq (pshost
->irq
, Irq_Handler
, SA_INTERRUPT
| SA_SHIRQ
, "pci2220i", padapter
) < 0 )
1874 printk ("Unable to allocate IRQ for PCI-2220I controller.\n");
1878 padapter
->irqOwned
= pshost
->irq
; // set IRQ as owned
1880 padapter
->kBuffer
= kmalloc (SECTORSXFER
* BYTES_PER_SECTOR
, GFP_DMA
| GFP_ATOMIC
);
1881 if ( !padapter
->kBuffer
)
1883 printk ("Unable to allocate DMA buffer for PCI-2220I controller.\n");
1884 #if LINUX_VERSION_CODE < LINUXVERSION(1,3,70)
1885 free_irq (pshost
->irq
);
1886 #else /* version >= v1.3.70 */
1887 free_irq (pshost
->irq
, padapter
);
1888 #endif /* version >= v1.3.70 */
1891 PsiHost
[installed
] = pshost
; // save SCSI_HOST pointer
1893 pshost
->io_port
= padapter
->basePort
;
1894 pshost
->n_io_port
= 0xFF;
1895 pshost
->unique_id
= padapter
->regBase
;
1898 outb_p (0x01, padapter
->regRange
); // fix our range register because other drivers want to tromp on it
1900 padapter
->timingMode
= inb_p (padapter
->regScratchPad
+ DALE_TIMING_MODE
);
1901 if ( padapter
->timingMode
>= 2 )
1902 padapter
->timingAddress
= ModeArray
[padapter
->timingMode
- 2];
1904 padapter
->timingPIO
= TRUE
;
1906 ReadFlash (padapter
, &DaleSetup
, DALE_FLASH_SETUP
, sizeof (SETUP
));
1907 for ( z
= 0; z
< inb_p (padapter
->regScratchPad
+ DALE_NUM_DRIVES
); ++z
)
1909 unit
= inb_p (padapter
->regScratchPad
+ DALE_CHANNEL_DEVICE_0
+ z
) & 0x0F;
1910 padapter
->device
[z
].device
= inb_p (padapter
->regScratchPad
+ DALE_SCRATH_DEVICE_0
+ unit
);
1911 padapter
->device
[z
].byte6
= (UCHAR
)(((unit
& 1) << 4) | 0xE0);
1912 padapter
->device
[z
].spigot
= (UCHAR
)(1 << (unit
>> 1));
1913 padapter
->device
[z
].sectors
= DaleSetup
.setupDevice
[unit
].sectors
;
1914 padapter
->device
[z
].heads
= DaleSetup
.setupDevice
[unit
].heads
;
1915 padapter
->device
[z
].cylinders
= DaleSetup
.setupDevice
[unit
].cylinders
;
1916 padapter
->device
[z
].blocks
= DaleSetup
.setupDevice
[unit
].blocks
;
1920 ReadFlash (padapter
, &DiskMirror
, DALE_FLASH_RAID
, sizeof (DiskMirror
));
1921 DiskMirror
[0].status
= inb_p (padapter
->regScratchPad
+ DALE_RAID_0_STATUS
);
1922 DiskMirror
[1].status
= inb_p (padapter
->regScratchPad
+ DALE_RAID_1_STATUS
);
1923 if ( (DiskMirror
[0].signature
== SIGNATURE
) && (DiskMirror
[1].signature
== SIGNATURE
) &&
1924 (DiskMirror
[0].pairIdentifier
== (DiskMirror
[1].pairIdentifier
^ 1)) )
1929 memcpy (padapter
->device
[z
].DiskMirror
, DiskMirror
, sizeof (DiskMirror
));
1930 padapter
->raidData
[0] = &padapter
->device
[z
].DiskMirror
[0];
1931 padapter
->raidData
[2] = &padapter
->device
[z
].DiskMirror
[1];
1935 padapter
->device
[z
].lastsectorlba
[0] = InlineIdentify (padapter
, 1, 0);
1936 padapter
->device
[z
].lastsectorlba
[1] = InlineIdentify (padapter
, 2, 0);
1938 if ( !(DiskMirror
[1].status
& UCBF_SURVIVOR
) && padapter
->device
[z
].lastsectorlba
[0] )
1940 if ( !(DiskMirror
[0].status
& UCBF_SURVIVOR
) && padapter
->device
[z
].lastsectorlba
[1] )
1942 if ( DiskMirror
[0].status
& UCBF_SURVIVOR
& DiskMirror
[1].status
& UCBF_SURVIVOR
)
1945 if ( spigot1
&& (DiskMirror
[0].status
& UCBF_REBUILD
) )
1946 InlineReadSignature (padapter
, &padapter
->device
[z
], 0);
1947 if ( spigot2
&& (DiskMirror
[1].status
& UCBF_REBUILD
) )
1948 InlineReadSignature (padapter
, &padapter
->device
[z
], 1);
1950 if ( spigot1
&& spigot2
)
1952 padapter
->device
[z
].raid
= 1;
1953 if ( DiskMirror
[0].status
& UCBF_REBUILD
)
1954 padapter
->device
[z
].spigot
= 2;
1956 padapter
->device
[z
].spigot
= 1;
1957 if ( (DiskMirror
[0].status
& UCBF_REBUILD
) || (DiskMirror
[1].status
& UCBF_REBUILD
) )
1959 padapter
->reconOn
= padapter
->reconIsStarting
= TRUE
;
1966 if ( DiskMirror
[0].status
& UCBF_REBUILD
)
1968 DiskMirror
[0].status
= UCBF_MIRRORED
| UCBF_SURVIVOR
;
1969 padapter
->device
[z
].spigot
= 1;
1973 if ( DiskMirror
[1].status
& UCBF_REBUILD
)
1975 DiskMirror
[1].status
= UCBF_MIRRORED
| UCBF_SURVIVOR
;
1976 padapter
->device
[z
].spigot
= 2;
1978 if ( DaleSetup
.rebootRebuil
)
1979 padapter
->reconOn
= padapter
->reconIsStarting
= TRUE
;
1987 init_timer (&padapter
->timer
);
1988 padapter
->timer
.function
= TimerExpiry
;
1989 padapter
->timer
.data
= (unsigned long)padapter
;
1990 init_timer (&padapter
->reconTimer
);
1991 padapter
->reconTimer
.function
= ReconTimerExpiry
;
1992 padapter
->reconTimer
.data
= (unsigned long)padapter
;
1993 printk("\nPCI-2220I EIDE CONTROLLER: at I/O = %X/%X IRQ = %d\n", padapter
->basePort
, padapter
->regBase
, pshost
->irq
);
1994 printk("Version %s, Compiled %s %s\n\n", PCI2220I_VERSION
, __DATE__
, __TIME__
);
1996 if ( ++installed
< MAXADAPTER
)
2000 scsi_unregister (pshost
);
2004 NumAdapters
= installed
;
2007 /****************************************************************
2008 * Name: Pci2220i_Abort
2010 * Description: Process the Abort command from the SCSI manager.
2012 * Parameters: SCpnt - Pointer to SCSI command structure.
2014 * Returns: Allways snooze.
2016 ****************************************************************/
2017 int Pci2220i_Abort (Scsi_Cmnd
*SCpnt
)
2019 return SCSI_ABORT_SNOOZE
;
2021 /****************************************************************
2022 * Name: Pci2220i_Reset
2024 * Description: Process the Reset command from the SCSI manager.
2026 * Parameters: SCpnt - Pointer to SCSI command structure.
2027 * flags - Flags about the reset command
2029 * Returns: No active command at this time, so this means
2030 * that each time we got some kind of response the
2031 * last time through. Tell the mid-level code to
2032 * request sense information in order to decide what
2035 ****************************************************************/
2036 int Pci2220i_Reset (Scsi_Cmnd
*SCpnt
, unsigned int reset_flags
)
2038 return SCSI_RESET_PUNT
;
2040 /****************************************************************
2041 * Name: Pci2220i_Release
2043 * Description: Release resources allocated for a single each adapter.
2045 * Parameters: pshost - Pointer to SCSI command structure.
2049 ****************************************************************/
2050 int Pci2220i_Release (struct Scsi_Host
*pshost
)
2052 PADAPTER2220I padapter
= HOSTDATA (pshost
);
2054 if ( padapter
->reconOn
)
2056 padapter
->reconOn
= FALSE
; // shut down the hot reconstruct
2057 if ( padapter
->reconPhase
)
2059 if ( padapter
->reconTimer
.data
) // is the timer running?
2061 del_timer (&padapter
->reconTimer
);
2062 padapter
->reconTimer
.data
= 0;
2066 // save RAID status on the board
2067 outb_p (DiskMirror
[0].status
, padapter
->regScratchPad
+ DALE_RAID_0_STATUS
);
2068 outb_p (DiskMirror
[1].status
, padapter
->regScratchPad
+ DALE_RAID_1_STATUS
);
2070 if ( padapter
->irqOwned
)
2071 #if LINUX_VERSION_CODE < LINUXVERSION(1,3,70)
2072 free_irq (pshost
->irq
);
2073 #else /* version >= v1.3.70 */
2074 free_irq (pshost
->irq
, padapter
);
2075 #endif /* version >= v1.3.70 */
2076 release_region (pshost
->io_port
, pshost
->n_io_port
);
2077 kfree (padapter
->kBuffer
);
2078 scsi_unregister(pshost
);
2084 /****************************************************************
2085 * Name: Pci2220i_BiosParam
2087 * Description: Process the biosparam request from the SCSI manager to
2088 * return C/H/S data.
2090 * Parameters: disk - Pointer to SCSI disk structure.
2091 * dev - Major/minor number from kernel.
2092 * geom - Pointer to integer array to place geometry data.
2096 ****************************************************************/
2097 int Pci2220i_BiosParam (Scsi_Disk
*disk
, kdev_t dev
, int geom
[])
2101 pdev
= &(HOSTDATA(disk
->device
->host
)->device
[disk
->device
->id
]);
2103 geom
[0] = pdev
->heads
;
2104 geom
[1] = pdev
->sectors
;
2105 geom
[2] = pdev
->cylinders
;
2111 /* Eventually this will go into an include file, but this will be later */
2112 Scsi_Host_Template driver_template
= PCI2220I
;
2114 #include "scsi_module.c"