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 typedefstruct
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 typedefstruct
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 voidReconTimerExpiry(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 voidMuteAlarm(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 intWaitReady(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 return0;
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 intWaitReadyReset(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 return0;
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 intWaitDrq(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 return0;
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 intHardReset(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 voidBusMaster(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 intWriteData(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 return0;
359 padapter->cmd =0;// null out the command byte
360 return1;
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 intWriteDataBoth(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 return0;
398 padapter->cmd =0;// null out the command byte
399 if( status0 )
400 return1;
401 return2;
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 return0;
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 return0;
470 padapter->cmd =0;// null out the command byte
471 if( status0 )
472 return1;
473 return2;
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 voidOpDone(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 return0;
540 WriteCommand(padapter, IDE_COMMAND_IDENTIFY);
541 if(WaitDrq(padapter) )
542 return0;
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 return0;
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 voidStartTimer(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 intWriteSignature(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 intInitFailover(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 voidTimerExpiry(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("\nspig/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 voidReconTimerExpiry(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 voidIrq_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 intPci2220i_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 return0;
1560 if( padapter->reconPhase )
1561 return0;
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 return0;
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 return0;
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 return0;
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 return0;
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 return0;
1657 if( padapter->reconPhase )
1658 return0;
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 return0;
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 return0;
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 return0;
1716 OpDone(padapter, DID_ERROR <<16);
1717 return0;
1720 return0;
1723 static voidinternal_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 intPci2220i_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 intPci2220i_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 return0;
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 intPci2220i_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 intPci2220i_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 intPci2220i_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 return0;
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 intPci2220i_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 return0;
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
close