Import 2.3.18pre1
[davej-history.git] / drivers / scsi / pci2220i.c
blobbdc28518642e3523516714c99695a8a0413df1ad
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 ****************************************************************************/
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>
43 #include <asm/dma.h>
44 #include <asm/system.h>
45 #include <asm/io.h>
46 #include "scsi.h"
47 #include "hosts.h"
48 #include "pci2220i.h"
50 #if LINUX_VERSION_CODE >= LINUXVERSION(2,1,95)
51 #include <linux/spinlock.h>
52 #endif
53 #if LINUX_VERSION_CODE < LINUXVERSION(2,1,93)
54 #include <linux/bios32.h>
55 #endif
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 };
69 //#define DEBUG 1
71 #ifdef DEBUG
72 #define DEB(x) x
73 #define STOP_HERE() {int st;for(st=0;st<100;st++){st=1;}}
74 #else
75 #define DEB(x)
76 #define STOP_HERE()
77 #endif
79 #define MAXADAPTER 4 // Increase this and the sizes of the arrays below, if you need more.
82 typedef struct
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
96 USHORT mirrorRecon;
97 UCHAR hotRecon;
98 USHORT reconCount;
99 } OUR_DEVICE, *POUR_DEVICE;
101 typedef struct
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];
133 ULONG startSector;
134 USHORT sectorCount;
135 UCHAR cmd;
136 Scsi_Cmnd *SCpnt;
137 VOID *buffer;
138 POUR_DEVICE pdev; // current device opearating on
139 USHORT expectingIRQ;
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.
143 ULONG reconSize;
144 USHORT demoFail; // flag for RAID failure demonstration
145 USHORT survivor;
146 USHORT failinprog;
147 struct timer_list reconTimer;
148 struct timer_list timer;
149 UCHAR *kBuffer;
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)
182 UCHAR old;
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)
199 ULONG z;
200 UCHAR status;
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 )
206 return 0;
207 udelay (250);
209 return status;
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)
223 ULONG z;
224 UCHAR status;
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));
232 return 0;
234 udelay (250);
236 DEB (printk ("\nPCI2220I: Reset took more than 1 Second to come ready, Disk Failure"));
237 return status;
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)
251 ULONG z;
252 UCHAR status;
254 for ( z = 0; z < (TIMEOUT_DRQ * 4); z++ )
256 status = inb_p (padapter->regStatCmd);
257 if ( status & IDE_STATUS_DRQ )
258 return 0;
259 udelay (250);
261 return status;
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
282 udelay (100);
283 outb_p (0xA0, padapter->regLba24); //Specify drive
285 outb_p (pdev->byte6, padapter->regLba24); // select the drive
286 if ( WaitReadyReset (padapter) )
287 return TRUE;
288 outb_p (SECTORSXFER, padapter->regSectCount);
289 WriteCommand (padapter, IDE_CMD_SET_MULTIPLE);
290 if ( WaitReady (padapter) )
291 return TRUE;
292 return FALSE;
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)
308 ULONG zl;
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);
317 if ( datain )
319 outb_p (8, padapter->regDmaDesc); // read operation
320 if ( irq && !padapter->sectorCount )
321 outb_p (5, padapter->regDmaMode); // interrupt on
322 else
323 outb_p (1, padapter->regDmaMode); // no interrupt
325 else
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)
344 ULONG zl;
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;
355 else
356 BusMaster (padapter, 0, 0);
357 return 0;
359 padapter->cmd = 0; // null out the command byte
360 return 1;
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)
374 ULONG zl;
375 UCHAR status0, status1;
377 SelectSpigot (padapter, 1);
378 status0 = WaitDrq (padapter);
379 if ( !status0 )
381 SelectSpigot (padapter, 2);
382 status1 = WaitDrq (padapter);
383 if ( !status1 )
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;
393 else
394 BusMaster (padapter, 0, 0);
395 return 0;
398 padapter->cmd = 0; // null out the command byte
399 if ( status0 )
400 return 1;
401 return 2;
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)
416 UCHAR status;
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);
421 if ( !status )
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);
429 return 0;
432 padapter->cmd = 0; // null out the command byte
433 return status;
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)
447 UCHAR status0;
448 UCHAR status1;
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);
454 if ( !status0 )
456 SelectSpigot (padapter, 2);
457 status1 = WaitReady (padapter);
458 if ( !status1 )
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);
467 return 0;
470 padapter->cmd = 0; // null out the command byte
471 if ( status0 )
472 return 1;
473 return 2;
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.
484 * Returns: Nothing.
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);
498 else
500 if ( padapter->reconOn )
502 ReconTimerExpiry ((unsigned long)padapter);
506 else
508 padapter->cmd = 0;
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) )
539 return 0;
540 WriteCommand (padapter, IDE_COMMAND_IDENTIFY);
541 if ( WaitDrq (padapter) )
542 return 0;
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)
560 UCHAR status;
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);
567 if ( !status )
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);
575 if ( !status )
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);
582 return 0;
585 return status;
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)
600 UCHAR error;
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));
612 switch ( error )
614 case IDE_ERROR_AMNF:
615 case IDE_ERROR_TKONF:
616 case IDE_ERROR_ABRT:
617 case IDE_ERROR_IDFN:
618 case IDE_ERROR_UNC:
619 case IDE_ERROR_BBK:
620 default:
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.
632 * Returns: Nothing.
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)
655 ULONG zl;
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) )
667 return TRUE;
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);
674 return FALSE;
676 /*******************************************************************************************************
677 * Name: InitFailover
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)
690 UCHAR spigot;
692 DEB (printk ("\npci2220i: Initialize failover process - survivor = %d", padapter->survivor));
693 pdev->raid = FALSE; //initializes system for non raid mode
694 pdev->hotRecon = 0;
695 padapter->reconOn = FALSE;
696 spigot = (padapter->survivor) ? 2 : 1;
698 if ( pdev->DiskMirror[padapter->survivor].status & UCBF_REBUILD )
699 return (TRUE);
701 if ( HardReset (padapter, pdev, spigot) )
702 return TRUE;
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) )
708 return TRUE;
709 padapter->failinprog = TRUE;
710 return FALSE;
712 /****************************************************************
713 * Name: TimerExpiry :LOCAL
715 * Description: Timer expiry routine.
717 * Parameters: data - Pointer adapter data structure.
719 * Returns: Nothing.
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;
727 UCHAR temp, temp1;
728 #if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
729 int flags;
730 #else /* version >= v2.1.95 */
731 unsigned long flags;
732 #endif /* version >= v2.1.95 */
734 #if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
735 /* Disable interrupts, if they aren't already disabled. */
736 save_flags (flags);
737 cli ();
738 #else /* version >= v2.1.95 */
740 * Disable interrupts, if they aren't already disabled and acquire
741 * the I/O spinlock.
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;
793 default:
794 goto timerExpiryDone;
798 while ( padapter->cmd )
800 outb_p (0x08, padapter->regDmaCmdStat); // cancel interrupt from DMA engine
801 if ( pdev->raid )
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);
811 else
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);
819 else
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) )
826 status = temp;
827 break;
829 else
831 if (temp & IDE_STATUS_BUSY)
832 padapter->survivor = 1;
833 else
834 padapter->survivor = 0;
835 DEB (printk ("\npci2220i: FAILURE 5"));
836 if ( InitFailover (padapter, pdev) )
838 status = inb_p (padapter->regStatCmd);
839 break;
841 goto timerExpiryDone;
845 else
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);
853 break;
855 goto timerExpiryDone;
858 else
860 DEB (printk ("in I/O operation"));
861 status = inb_p (padapter->regStatCmd);
863 break;
866 OpDone (padapter, DecodeError (padapter, status));
868 timerExpiryDone:;
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
879 * enabled on entry.
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.
911 * Returns: Nothing.
913 ****************************************************************/
914 static void ReconTimerExpiry (unsigned long data)
916 PADAPTER2220I padapter;
917 POUR_DEVICE pdev;
918 ULONG testsize = 0;
919 PIDENTIFY_DATA pid;
920 USHORT minmode;
921 ULONG zl;
922 UCHAR zc;
923 #if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
924 int flags;
925 #else /* version >= v2.1.95 */
926 unsigned long flags;
927 #endif /* version >= v2.1.95 */
929 #if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
930 /* Disable interrupts, if they aren't already disabled. */
931 save_flags (flags);
932 cli ();
933 #else /* version >= v2.1.95 */
935 * Disable interrupts, if they aren't already disabled and acquire
936 * the I/O spinlock.
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);
965 else
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 )
973 pdev->hotRecon = 1;
974 pdev->mirrorRecon = 0;
976 else
978 pdev->hotRecon = 2;
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);
990 while ( 1 )
992 if ( HardReset (padapter, pdev, pdev->hotRecon) )
994 DEB (printk ("\npci2220i: sub 1"));
995 break;
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));
1003 break;
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"));
1010 break;
1013 // test PIO/bus matering mode compatability
1014 if ( (pid->MinPIOCycleWithoutFlow > 240) && !pid->SupportIORDYDisable && !padapter->timingPIO )
1016 DEB (printk ("\npci2220i: sub 4"));
1017 break;
1020 if ( pid->MinPIOCycleWithoutFlow <= 120 ) // setup timing mode of drive
1021 minmode = 5;
1022 else
1024 if ( pid->MinPIOCylceWithFlow <= 150 )
1025 minmode = 4;
1026 else
1028 if ( pid->MinPIOCylceWithFlow <= 180 )
1029 minmode = 3;
1030 else
1032 if ( pid->MinPIOCylceWithFlow <= 240 )
1033 minmode = 2;
1034 else
1036 DEB (printk ("\npci2220i: sub 5"));
1037 break;
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];
1047 else
1048 padapter->timingPIO = TRUE;
1050 padapter->reconOn = TRUE;
1051 break;
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;
1064 pdev->raid = TRUE;
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;
1134 reconTimerExpiry:;
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
1145 * enabled on entry.
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.
1156 * dev_id -
1157 * regs -
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
1166 POUR_DEVICE pdev;
1167 Scsi_Cmnd *SCpnt;
1168 UCHAR status;
1169 UCHAR status1;
1170 int z;
1171 ULONG zl;
1172 #if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
1173 int flags;
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. */
1180 save_flags (flags);
1181 cli ();
1182 #else /* version >= v2.1.95 */
1184 * Disable interrupts, if they aren't already disabled and acquire
1185 * the I/O spinlock.
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 )
1198 shost = PsiHost[z];
1199 break;
1204 if ( !shost )
1206 DEB (printk ("\npci2220i: not my interrupt"));
1207 goto irq_return;
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"));
1217 STOP_HERE ();
1218 goto irq_return;
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));
1231 padapter->cmd = 0;
1233 else
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);
1240 else
1241 Pci2220i_QueueCommand (SCpnt, SCpnt->scsi_done);
1242 goto irq_return;
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));
1262 goto irq_return;
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));
1270 goto irq_return;
1272 padapter->reconPhase = RECON_PHASE_END;
1273 goto irq_return;
1275 OpDone (padapter, DID_OK << 16);
1276 goto irq_return;
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));
1284 goto irq_return;
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));
1294 goto irq_return;
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));
1303 else
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
1312 goto irq_return;
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));
1327 goto irq_return;
1329 OpDone (padapter, DID_OK << 16);
1330 goto irq_return;
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));
1341 goto irq_return;
1343 padapter->reconOn = FALSE;
1344 pdev->hotRecon = 0;
1345 OpDone (padapter, DID_OK << 16);
1346 goto irq_return;
1348 default:
1349 goto irq_return;
1353 switch ( padapter->cmd ) // decide how to handle the interrupt
1355 case READ_CMD:
1356 if ( padapter->sectorCount )
1358 status = inb_p (padapter->regStatCmd); // read the device status
1359 if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
1361 if ( pdev->raid )
1363 padapter->survivor = (pdev->spigot ^ 3) >> 1;
1364 del_timer (&padapter->timer);
1365 DEB (printk ("\npci2220i: FAILURE 15"));
1366 if ( !InitFailover (padapter, pdev) )
1367 goto irq_return;
1369 break;
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 )
1379 status = 0;
1380 break;
1383 else
1384 BusMaster (padapter, 1, 1);
1385 padapter->expectingIRQ = TRUE;
1386 goto irq_return;
1388 status = 0;
1389 break;
1391 case WRITE_CMD:
1392 SelectSpigot (padapter, pdev->spigot | 0x80);
1393 status = inb_p (padapter->regStatCmd); // read the device status
1394 if ( pdev->raid )
1396 SelectSpigot (padapter, (pdev->spigot ^ 3) | 0x80);
1397 status1 = inb_p (padapter->regStatCmd); // read the device status
1399 else
1400 status1 = 0;
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) )
1411 goto irq_return;
1413 break;
1415 if ( pdev->raid )
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) )
1423 goto irq_return;
1424 status = status1;
1425 break;
1427 if ( padapter->sectorCount )
1429 status = WriteDataBoth (padapter);
1430 if ( status )
1432 padapter->survivor = (status ^ 3) >> 1;
1433 del_timer (&padapter->timer);
1434 DEB (printk ("\npci2220i: FAILURE 18"));
1435 if ( !InitFailover (padapter, pdev) )
1436 goto irq_return;
1437 SelectSpigot (padapter, status | 0x80);
1438 status = inb_p (padapter->regStatCmd); // read the device status
1439 break;
1441 padapter->expectingIRQ = TRUE;
1442 goto irq_return;
1444 status = 0;
1445 break;
1447 if ( padapter->sectorCount )
1449 SelectSpigot (padapter, pdev->spigot);
1450 status = WriteData (padapter);
1451 if ( status )
1452 break;
1453 padapter->expectingIRQ = TRUE;
1454 goto irq_return;
1456 status = 0;
1457 break;
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;
1495 status = 0;
1497 break;
1500 default:
1501 status = 0;
1502 break;
1505 del_timer (&padapter->timer);
1506 if ( status )
1508 DEB (printk ("\npci2220i Interupt hanlder return error"));
1509 zl = DecodeError (padapter, status);
1511 else
1512 zl = DID_OK << 16;
1514 OpDone (padapter, zl);
1515 irq_return:;
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
1526 * enabled on entry.
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
1548 int z;
1549 PDEVICE_RAID1 pdr;
1551 SCpnt->scsi_done = done;
1552 padapter->buffer = SCpnt->request_buffer;
1553 padapter->SCpnt = SCpnt; // Save this command data
1554 if ( !done )
1556 printk("pci2220i_queuecommand: %02X: done can't be NULL\n", *cdb);
1557 return 0;
1560 if ( padapter->reconPhase )
1561 return 0;
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);
1571 return 0;
1575 switch ( *cdb )
1577 case SCSIOP_INQUIRY: // inquiry CDB
1579 if ( cdb[2] == SC_MY_RAID )
1581 switch ( cdb[3] )
1583 case MY_SCSI_REBUILD:
1584 padapter->reconOn = padapter->reconIsStarting = TRUE;
1585 OpDone (padapter, DID_OK << 16);
1586 break;
1587 case MY_SCSI_ALARMMUTE:
1588 MuteAlarm (padapter);
1589 OpDone (padapter, DID_OK << 16);
1590 break;
1591 case MY_SCSI_DEMOFAIL:
1592 padapter->demoFail = TRUE;
1593 OpDone (padapter, DID_OK << 16);
1594 break;
1595 default:
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;
1603 else
1604 memset (pdr, 0, sizeof (DEVICE_RAID1));
1605 OpDone (padapter, DID_OK << 16);
1606 break;
1608 return 0;
1610 padapter->cmd = IDE_COMMAND_IDENTIFY;
1611 break;
1614 case SCSIOP_TEST_UNIT_READY: // test unit ready CDB
1615 OpDone (padapter, DID_OK << 16);
1616 return 0;
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);
1624 return 0;
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;
1630 break;
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;
1635 break;
1636 case SCSIOP_READ6: // read6 CDB
1637 padapter->startSector = SCSI2LONG (&cdb[1]);
1638 padapter->sectorCount = cdb[4];
1639 padapter->cmd = READ_CMD;
1640 break;
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;
1645 break;
1646 case SCSIOP_WRITE6: // write6 CDB
1647 padapter->startSector = SCSI2LONG (&cdb[1]);
1648 padapter->sectorCount = cdb[4];
1649 padapter->cmd = WRITE_CMD;
1650 break;
1651 default:
1652 DEB (printk ("pci2220i_queuecommand: Unsupported command %02X\n", *cdb));
1653 OpDone (padapter, DID_ERROR << 16);
1654 return 0;
1657 if ( padapter->reconPhase )
1658 return 0;
1660 padapter->pdev = pdev;
1662 while ( padapter->demoFail )
1664 padapter->demoFail = FALSE;
1665 if ( !pdev->raid ||
1666 (pdev->DiskMirror[0].status & UCBF_SURVIVOR) ||
1667 (pdev->DiskMirror[1].status & UCBF_SURVIVOR) )
1669 break;
1671 if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
1672 padapter->survivor = 1;
1673 else
1674 padapter->survivor = 0;
1675 DEB (printk ("\npci2220i: FAILURE 19"));
1676 if ( InitFailover (padapter, pdev ) )
1677 break;
1678 return 0;
1681 StartTimer (padapter);
1682 if ( pdev->raid && (padapter->cmd == WRITE_CMD) )
1684 rc = IdeCmdBoth (padapter);
1685 if ( !rc )
1686 rc = WriteDataBoth (padapter);
1687 if ( rc )
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);
1696 return 0;
1700 else
1702 rc = IdeCmd (padapter, pdev);
1703 if ( (padapter->cmd == WRITE_CMD) && !rc )
1704 rc = WriteData (padapter);
1705 if ( rc )
1707 del_timer (&padapter->timer);
1708 padapter->expectingIRQ = 0;
1709 if ( pdev->raid )
1711 padapter->survivor = (pdev->spigot ^ 3) >> 1;
1712 DEB (printk ("\npci2220i: FAILURE 21"));
1713 if ( !InitFailover (padapter, pdev) )
1714 return 0;
1716 OpDone (padapter, DID_ERROR << 16);
1717 return 0;
1720 return 0;
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)
1742 barrier ();
1743 return SCpnt->result;
1745 /****************************************************************
1746 * Name: ReadFlash
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.
1755 * Returns: Nothing.
1757 ****************************************************************/
1758 VOID ReadFlash (PADAPTER2220I padapter, VOID *pdata, ULONG base, ULONG length)
1760 ULONG oldremap;
1761 UCHAR olddesc;
1762 ULONG z;
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)
1788 int found = 0;
1789 int installed = 0;
1790 struct Scsi_Host *pshost;
1791 PADAPTER2220I padapter;
1792 int unit;
1793 int z;
1794 USHORT zs;
1795 USHORT raidon = FALSE;
1796 int setirq;
1797 UCHAR spigot1 = FALSE;
1798 UCHAR spigot2 = FALSE;
1799 #if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
1800 struct pci_dev *pdev = NULL;
1801 #else
1802 UCHAR pci_bus, pci_device_fn;
1803 #endif
1805 #if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
1806 if ( !pci_present () )
1807 #else
1808 if ( !pcibios_present () )
1809 #endif
1811 printk ("pci2220i: PCI BIOS not present\n");
1812 return 0;
1815 #if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
1816 while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_DALE_1, pdev)) != NULL )
1817 #else
1818 while ( !pcibios_find_device (VENDOR_PSI, DEVICE_DALE_1, found, &pci_bus, &pci_device_fn) )
1819 #endif
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
1855 goto unregister;
1857 #if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
1858 pshost->irq = pdev->irq;
1859 #else
1860 pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq);
1861 #endif
1862 setirq = 1;
1863 for ( z = 0; z < installed; z++ ) // scan for shared interrupts
1865 if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses
1866 setirq = 0;
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");
1875 goto unregister;
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 */
1889 goto unregister;
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;
1896 pshost->max_id = 4;
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];
1903 else
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;
1918 if ( !z )
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)) )
1926 raidon = TRUE;
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];
1933 if ( raidon )
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] )
1939 spigot1 = TRUE;
1940 if ( !(DiskMirror[0].status & UCBF_SURVIVOR) && padapter->device[z].lastsectorlba[1] )
1941 spigot2 = TRUE;
1942 if ( DiskMirror[0].status & UCBF_SURVIVOR & DiskMirror[1].status & UCBF_SURVIVOR )
1943 spigot1 = TRUE;
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;
1955 else
1956 padapter->device[z].spigot = 1;
1957 if ( (DiskMirror[0].status & UCBF_REBUILD) || (DiskMirror[1].status & UCBF_REBUILD) )
1959 padapter->reconOn = padapter->reconIsStarting = TRUE;
1962 else
1964 if ( spigot1 )
1966 if ( DiskMirror[0].status & UCBF_REBUILD )
1967 goto unregister;
1968 DiskMirror[0].status = UCBF_MIRRORED | UCBF_SURVIVOR;
1969 padapter->device[z].spigot = 1;
1971 else
1973 if ( DiskMirror[1].status & UCBF_REBUILD )
1974 goto unregister;
1975 DiskMirror[1].status = UCBF_MIRRORED | UCBF_SURVIVOR;
1976 padapter->device[z].spigot = 2;
1978 if ( DaleSetup.rebootRebuil )
1979 padapter->reconOn = padapter->reconIsStarting = TRUE;
1982 break;
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__);
1995 found++;
1996 if ( ++installed < MAXADAPTER )
1997 continue;
1998 break;;
1999 unregister:;
2000 scsi_unregister (pshost);
2001 found++;
2004 NumAdapters = installed;
2005 return 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
2033 * to do next.
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.
2047 * Returns: zero.
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 )
2058 udelay (300000);
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);
2079 return 0;
2082 #include "sd.h"
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.
2094 * Returns: zero.
2096 ****************************************************************/
2097 int Pci2220i_BiosParam (Scsi_Disk *disk, kdev_t dev, int geom[])
2099 POUR_DEVICE pdev;
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;
2106 return 0;
2110 #ifdef MODULE
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"
2115 #endif