aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/pci2220i.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/scsi/pci2220i.c
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/scsi/pci2220i.c')
-rw-r--r--drivers/scsi/pci2220i.c2915
1 files changed, 2915 insertions, 0 deletions
diff --git a/drivers/scsi/pci2220i.c b/drivers/scsi/pci2220i.c
new file mode 100644
index 00000000000..e395e420315
--- /dev/null
+++ b/drivers/scsi/pci2220i.c
@@ -0,0 +1,2915 @@
1/****************************************************************************
2 * Perceptive Solutions, Inc. PCI-2220I device driver for Linux.
3 *
4 * pci2220i.c - Linux Host Driver for PCI-2220I EIDE RAID Adapters
5 *
6 * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
7 * All Rights Reserved.
8 *
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.
13 *
14 * Technical updates and product information at:
15 * http://www.psidisk.com
16 *
17 * Please send questions, comments, bug reports to:
18 * tech@psidisk.com Technical Support
19 *
20 *
21 * Revisions 1.10 Mar-26-1999
22 * - Updated driver for RAID and hot reconstruct support.
23 *
24 * Revisions 1.11 Mar-26-1999
25 * - Fixed spinlock and PCI configuration.
26 *
27 * Revision 2.00 December-1-1999
28 * - Added code for the PCI-2240I controller
29 * - Added code for ATAPI devices.
30 * - Double buffer for scatter/gather support
31 *
32 * Revision 2.10 March-27-2000
33 * - Added support for dynamic DMA
34 *
35 ****************************************************************************/
36
37#error Convert me to understand page+offset based scatterlists
38
39//#define DEBUG 1
40
41#include <linux/interrupt.h>
42#include <linux/module.h>
43#include <linux/kernel.h>
44#include <linux/types.h>
45#include <linux/string.h>
46#include <linux/slab.h>
47#include <linux/pci.h>
48#include <linux/ioport.h>
49#include <linux/delay.h>
50#include <linux/sched.h>
51#include <linux/proc_fs.h>
52#include <linux/stat.h>
53#include <linux/blkdev.h>
54#include <linux/timer.h>
55#include <linux/spinlock.h>
56
57#include <asm/dma.h>
58#include <asm/system.h>
59#include <asm/io.h>
60
61#include "scsi.h"
62#include <scsi/scsi_host.h>
63#include "pci2220i.h"
64#include "psi_dale.h"
65
66
67#define PCI2220I_VERSION "2.10"
68#define READ_CMD IDE_CMD_READ_MULTIPLE
69#define WRITE_CMD IDE_CMD_WRITE_MULTIPLE
70#define MAX_BUS_MASTER_BLOCKS SECTORSXFER // This is the maximum we can bus master
71
72#ifdef DEBUG
73#define DEB(x) x
74#define STOP_HERE() {int st;for(st=0;st<100;st++){st=1;}}
75#else
76#define DEB(x)
77#define STOP_HERE()
78#endif
79
80#define MAXADAPTER 4 // Increase this and the sizes of the arrays below, if you need more.
81
82
83typedef struct
84 {
85 UCHAR byte6; // device select register image
86 UCHAR spigot; // spigot number
87 UCHAR spigots[2]; // RAID spigots
88 UCHAR deviceID[2]; // device ID codes
89 USHORT sectors; // number of sectors per track
90 USHORT heads; // number of heads
91 USHORT cylinders; // number of cylinders for this device
92 USHORT spareword; // placeholder
93 ULONG blocks; // number of blocks on device
94 DISK_MIRROR DiskMirror[2]; // RAID status and control
95 ULONG lastsectorlba[2]; // last addressable sector on the drive
96 USHORT raid; // RAID active flag
97 USHORT mirrorRecon;
98 UCHAR reconOn;
99 USHORT reconCount;
100 USHORT reconIsStarting; // indicate hot reconstruct is starting
101 UCHAR cmdDrqInt; // flag for command interrupt
102 UCHAR packet; // command packet size in bytes
103 } OUR_DEVICE, *POUR_DEVICE;
104
105typedef struct
106 {
107 USHORT bigD; // identity is a PCI-2240I if true, otherwise a PCI-2220I
108 USHORT atapi; // this interface is for ATAPI devices only
109 ULONG regDmaDesc; // address of the DMA discriptor register for direction of transfer
110 ULONG regDmaCmdStat; // Byte #1 of DMA command status register
111 ULONG regDmaAddrPci; // 32 bit register for PCI address of DMA
112 ULONG regDmaAddrLoc; // 32 bit register for local bus address of DMA
113 ULONG regDmaCount; // 32 bit register for DMA transfer count
114 ULONG regDmaMode; // 32 bit register for DMA mode control
115 ULONG regRemap; // 32 bit local space remap
116 ULONG regDesc; // 32 bit local region descriptor
117 ULONG regRange; // 32 bit local range
118 ULONG regIrqControl; // 16 bit Interrupt enable/disable and status
119 ULONG regScratchPad; // scratch pad I/O base address
120 ULONG regBase; // Base I/O register for data space
121 ULONG regData; // data register I/O address
122 ULONG regError; // error register I/O address
123 ULONG regSectCount; // sector count register I/O address
124 ULONG regLba0; // least significant byte of LBA
125 ULONG regLba8; // next least significant byte of LBA
126 ULONG regLba16; // next most significan byte of LBA
127 ULONG regLba24; // head and most 4 significant bits of LBA
128 ULONG regStatCmd; // status on read and command on write register
129 ULONG regStatSel; // board status on read and spigot select on write register
130 ULONG regFail; // fail bits control register
131 ULONG regAltStat; // alternate status and drive control register
132 ULONG basePort; // PLX base I/O port
133 USHORT timingMode; // timing mode currently set for adapter
134 USHORT timingPIO; // TRUE if PIO timing is active
135 struct pci_dev *pcidev;
136 ULONG timingAddress; // address to use on adapter for current timing mode
137 ULONG irqOwned; // owned IRQ or zero if shared
138 UCHAR numberOfDrives; // saved number of drives on this controller
139 UCHAR failRegister; // current inverted data in fail register
140 OUR_DEVICE device[BIGD_MAXDRIVES];
141 DISK_MIRROR *raidData[BIGD_MAXDRIVES];
142 ULONG startSector;
143 USHORT sectorCount;
144 ULONG readCount;
145 UCHAR *currentSgBuffer;
146 ULONG currentSgCount;
147 USHORT nextSg;
148 UCHAR cmd;
149 Scsi_Cmnd *SCpnt;
150 POUR_DEVICE pdev; // current device opearating on
151 USHORT devInReconIndex;
152 USHORT expectingIRQ;
153 USHORT reconOn; // Hot reconstruct is to be done.
154 USHORT reconPhase; // Hot reconstruct operation is in progress.
155 ULONG reconSize;
156 USHORT demoFail; // flag for RAID failure demonstration
157 USHORT survivor;
158 USHORT failinprog;
159 struct timer_list reconTimer;
160 struct timer_list timer;
161 UCHAR *kBuffer;
162 dma_addr_t kBufferDma;
163 UCHAR reqSense;
164 UCHAR atapiCdb[16];
165 UCHAR atapiSpecial;
166 } ADAPTER2220I, *PADAPTER2220I;
167
168#define HOSTDATA(host) ((PADAPTER2220I)&host->hostdata)
169
170#define RECON_PHASE_READY 0x01
171#define RECON_PHASE_COPY 0x02
172#define RECON_PHASE_UPDATE 0x03
173#define RECON_PHASE_LAST 0x04
174#define RECON_PHASE_END 0x07
175#define RECON_PHASE_MARKING 0x80
176#define RECON_PHASE_FAILOVER 0xFF
177
178static struct Scsi_Host *PsiHost[MAXADAPTER] = {NULL,}; // One for each adapter
179static int NumAdapters = 0;
180static int Installed = 0;
181static SETUP DaleSetup;
182static DISK_MIRROR DiskMirror[BIGD_MAXDRIVES];
183static ULONG ModeArray[] = {DALE_DATA_MODE2, DALE_DATA_MODE3, DALE_DATA_MODE4, DALE_DATA_MODE5};
184static ULONG ModeArray2[] = {BIGD_DATA_MODE2, BIGD_DATA_MODE3, BIGD_DATA_MODE4, BIGD_DATA_MODE5};
185
186static void ReconTimerExpiry (unsigned long data);
187
188/*******************************************************************************************************
189 * Name: Alarm
190 *
191 * Description: Sound the for the given device
192 *
193 * Parameters: padapter - Pointer adapter data structure.
194 * device - Device number.
195 *
196 * Returns: Nothing.
197 *
198 ******************************************************************************************************/
199static void Alarm (PADAPTER2220I padapter, UCHAR device)
200 {
201 UCHAR zc;
202
203 if ( padapter->bigD )
204 {
205 zc = device | (FAIL_ANY | FAIL_AUDIBLE);
206 if ( padapter->failRegister & FAIL_ANY )
207 zc |= FAIL_MULTIPLE;
208
209 padapter->failRegister = zc;
210 outb_p (~zc, padapter->regFail);
211 }
212 else
213 outb_p (0x3C | (1 << device), padapter->regFail); // sound alarm and set fail light
214 }
215/****************************************************************
216 * Name: MuteAlarm :LOCAL
217 *
218 * Description: Mute the audible alarm.
219 *
220 * Parameters: padapter - Pointer adapter data structure.
221 *
222 * Returns: TRUE if drive does not assert DRQ in time.
223 *
224 ****************************************************************/
225static void MuteAlarm (PADAPTER2220I padapter)
226 {
227 UCHAR old;
228
229 if ( padapter->bigD )
230 {
231 padapter->failRegister &= ~FAIL_AUDIBLE;
232 outb_p (~padapter->failRegister, padapter->regFail);
233 }
234 else
235 {
236 old = (inb_p (padapter->regStatSel) >> 3) | (inb_p (padapter->regStatSel) & 0x83);
237 outb_p (old | 0x40, padapter->regFail);
238 }
239 }
240/****************************************************************
241 * Name: WaitReady :LOCAL
242 *
243 * Description: Wait for device ready.
244 *
245 * Parameters: padapter - Pointer adapter data structure.
246 *
247 * Returns: TRUE if drive does not assert DRQ in time.
248 *
249 ****************************************************************/
250static int WaitReady (PADAPTER2220I padapter)
251 {
252 ULONG z;
253 UCHAR status;
254
255 for ( z = 0; z < (TIMEOUT_READY * 4); z++ )
256 {
257 status = inb_p (padapter->regStatCmd);
258 if ( (status & (IDE_STATUS_DRDY | IDE_STATUS_BUSY)) == IDE_STATUS_DRDY )
259 return 0;
260 udelay (250);
261 }
262 return status;
263 }
264/****************************************************************
265 * Name: WaitReadyReset :LOCAL
266 *
267 * Description: Wait for device ready.
268 *
269 * Parameters: padapter - Pointer adapter data structure.
270 *
271 * Returns: TRUE if drive does not assert DRQ in time.
272 *
273 ****************************************************************/
274static int WaitReadyReset (PADAPTER2220I padapter)
275 {
276 ULONG z;
277 UCHAR status;
278
279 for ( z = 0; z < (125 * 16); z++ ) // wait up to 1/4 second
280 {
281 status = inb_p (padapter->regStatCmd);
282 if ( (status & (IDE_STATUS_DRDY | IDE_STATUS_BUSY)) == IDE_STATUS_DRDY )
283 {
284 DEB (printk ("\nPCI2220I: Reset took %ld mSec to be ready", z / 8));
285 return 0;
286 }
287 udelay (125);
288 }
289 DEB (printk ("\nPCI2220I: Reset took more than 2 Seconds to come ready, Disk Failure"));
290 return status;
291 }
292/****************************************************************
293 * Name: WaitDrq :LOCAL
294 *
295 * Description: Wait for device ready for data transfer.
296 *
297 * Parameters: padapter - Pointer adapter data structure.
298 *
299 * Returns: TRUE if drive does not assert DRQ in time.
300 *
301 ****************************************************************/
302static int WaitDrq (PADAPTER2220I padapter)
303 {
304 ULONG z;
305 UCHAR status;
306
307 for ( z = 0; z < (TIMEOUT_DRQ * 4); z++ )
308 {
309 status = inb_p (padapter->regStatCmd);
310 if ( status & IDE_STATUS_DRQ )
311 return 0;
312 udelay (250);
313 }
314 return status;
315 }
316/****************************************************************
317 * Name: AtapiWaitReady :LOCAL
318 *
319 * Description: Wait for device busy and DRQ to be cleared.
320 *
321 * Parameters: padapter - Pointer adapter data structure.
322 * msec - Number of milliseconds to wait.
323 *
324 * Returns: TRUE if drive does not clear busy in time.
325 *
326 ****************************************************************/
327static int AtapiWaitReady (PADAPTER2220I padapter, int msec)
328 {
329 int z;
330
331 for ( z = 0; z < (msec * 16); z++ )
332 {
333 if ( !(inb_p (padapter->regStatCmd) & (IDE_STATUS_BUSY | IDE_STATUS_DRQ)) )
334 return FALSE;
335 udelay (125);
336 }
337 return TRUE;
338 }
339/****************************************************************
340 * Name: AtapiWaitDrq :LOCAL
341 *
342 * Description: Wait for device ready for data transfer.
343 *
344 * Parameters: padapter - Pointer adapter data structure.
345 * msec - Number of milliseconds to wait.
346 *
347 * Returns: TRUE if drive does not assert DRQ in time.
348 *
349 ****************************************************************/
350static int AtapiWaitDrq (PADAPTER2220I padapter, int msec)
351 {
352 ULONG z;
353
354 for ( z = 0; z < (msec * 16); z++ )
355 {
356 if ( inb_p (padapter->regStatCmd) & IDE_STATUS_DRQ )
357 return 0;
358 udelay (128);
359 }
360 return TRUE;
361 }
362/****************************************************************
363 * Name: HardReset :LOCAL
364 *
365 * Description: Wait for device ready for data transfer.
366 *
367 * Parameters: padapter - Pointer adapter data structure.
368 * pdev - Pointer to device.
369 * spigot - Spigot number.
370 *
371 * Returns: TRUE if drive does not assert DRQ in time.
372 *
373 ****************************************************************/
374static int HardReset (PADAPTER2220I padapter, POUR_DEVICE pdev, UCHAR spigot)
375 {
376 DEB (printk ("\npci2220i:RESET spigot = %X devices = %d, %d", spigot, pdev->deviceID[0], pdev->deviceID[1]));
377 mdelay (100); // just wait 100 mSec to let drives flush
378 SelectSpigot (padapter, spigot | SEL_IRQ_OFF);
379
380 outb_p (0x0E, padapter->regAltStat); // reset the suvivor
381 udelay (100); // wait a little
382 outb_p (0x08, padapter->regAltStat); // clear the reset
383 udelay (100);
384
385 outb_p (0xA0, padapter->regLba24); // select the master drive
386 if ( WaitReadyReset (padapter) )
387 {
388 DEB (printk ("\npci2220i: master not ready after reset"));
389 return TRUE;
390 }
391 outb_p (0xB0, padapter->regLba24); // try the slave drive
392 if ( (inb_p (padapter->regStatCmd) & (IDE_STATUS_DRDY | IDE_STATUS_BUSY)) == IDE_STATUS_DRDY )
393 {
394 DEB (printk ("\nPCI2220I: initializing slave drive on spigot %X", spigot));
395 outb_p (SECTORSXFER, padapter->regSectCount);
396 WriteCommand (padapter, IDE_CMD_SET_MULTIPLE);
397 if ( WaitReady (padapter) )
398 {
399 DEB (printk ("\npci2220i: slave not ready after set multiple"));
400 return TRUE;
401 }
402 }
403
404 outb_p (0xA0, padapter->regLba24); // select the drive
405 outb_p (SECTORSXFER, padapter->regSectCount);
406 WriteCommand (padapter, IDE_CMD_SET_MULTIPLE);
407 if ( WaitReady (padapter) )
408 {
409 DEB (printk ("\npci2220i: master not ready after set multiple"));
410 return TRUE;
411 }
412 return FALSE;
413 }
414/****************************************************************
415 * Name: AtapiReset :LOCAL
416 *
417 * Description: Wait for device ready for data transfer.
418 *
419 * Parameters: padapter - Pointer adapter data structure.
420 * pdev - Pointer to device.
421 *
422 * Returns: TRUE if drive does not come ready.
423 *
424 ****************************************************************/
425static int AtapiReset (PADAPTER2220I padapter, POUR_DEVICE pdev)
426 {
427 SelectSpigot (padapter, pdev->spigot);
428 AtapiDevice (padapter, pdev->byte6);
429 AtapiCountLo (padapter, 0);
430 AtapiCountHi (padapter, 0);
431 WriteCommand (padapter, IDE_COMMAND_ATAPI_RESET);
432 udelay (125);
433 if ( AtapiWaitReady (padapter, 1000) )
434 return TRUE;
435 if ( inb_p (padapter->regStatCmd) || (inb_p (padapter->regLba8) != 0x14) || (inb_p (padapter->regLba16) != 0xEB) )
436 return TRUE;
437 return FALSE;
438 }
439/****************************************************************
440 * Name: WalkScatGath :LOCAL
441 *
442 * Description: Transfer data to/from scatter/gather buffers.
443 *
444 * Parameters: padapter - Pointer adapter data structure.
445 * datain - TRUE if data read.
446 * length - Number of bytes to transfer.
447 *
448 * Returns: Nothing.
449 *
450 ****************************************************************/
451static void WalkScatGath (PADAPTER2220I padapter, UCHAR datain, ULONG length)
452 {
453 ULONG count;
454 UCHAR *buffer = padapter->kBuffer;
455
456 while ( length )
457 {
458 count = ( length > padapter->currentSgCount ) ? padapter->currentSgCount : length;
459
460 if ( datain )
461 memcpy (padapter->currentSgBuffer, buffer, count);
462 else
463 memcpy (buffer, padapter->currentSgBuffer, count);
464
465 padapter->currentSgCount -= count;
466 if ( !padapter->currentSgCount )
467 {
468 if ( padapter->nextSg < padapter->SCpnt->use_sg )
469 {
470 padapter->currentSgBuffer = ((struct scatterlist *)padapter->SCpnt->request_buffer)[padapter->nextSg].address;
471 padapter->currentSgCount = ((struct scatterlist *)padapter->SCpnt->request_buffer)[padapter->nextSg].length;
472 padapter->nextSg++;
473 }
474 }
475 else
476 padapter->currentSgBuffer += count;
477
478 length -= count;
479 buffer += count;
480 }
481 }
482/****************************************************************
483 * Name: BusMaster :LOCAL
484 *
485 * Description: Do a bus master I/O.
486 *
487 * Parameters: padapter - Pointer adapter data structure.
488 * datain - TRUE if data read.
489 * irq - TRUE if bus master interrupt expected.
490 *
491 * Returns: Nothing.
492 *
493 ****************************************************************/
494static void BusMaster (PADAPTER2220I padapter, UCHAR datain, UCHAR irq)
495 {
496 ULONG zl;
497
498 zl = ( padapter->sectorCount > MAX_BUS_MASTER_BLOCKS ) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
499 padapter->sectorCount -= zl;
500 zl *= (ULONG)BYTES_PER_SECTOR;
501
502 if ( datain )
503 {
504 padapter->readCount = zl;
505 outb_p (8, padapter->regDmaDesc); // read operation
506 if ( padapter->bigD )
507 {
508 if ( irq && !padapter->sectorCount )
509 outb_p (0x0C, padapter->regDmaMode); // interrupt on
510 else
511 outb_p (0x08, padapter->regDmaMode); // no interrupt
512 }
513 else
514 {
515 if ( irq && !padapter->sectorCount )
516 outb_p (0x05, padapter->regDmaMode); // interrupt on
517 else
518 outb_p (0x01, padapter->regDmaMode); // no interrupt
519 }
520 }
521 else
522 {
523 outb_p (0x00, padapter->regDmaDesc); // write operation
524 if ( padapter->bigD )
525 outb_p (0x08, padapter->regDmaMode); // no interrupt
526 else
527 outb_p (0x01, padapter->regDmaMode); // no interrupt
528 WalkScatGath (padapter, FALSE, zl);
529 }
530
531 outl (padapter->timingAddress, padapter->regDmaAddrLoc);
532 outl (padapter->kBufferDma, padapter->regDmaAddrPci);
533 outl (zl, padapter->regDmaCount);
534 outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear
535 }
536/****************************************************************
537 * Name: AtapiBusMaster :LOCAL
538 *
539 * Description: Do a bus master I/O.
540 *
541 * Parameters: padapter - Pointer adapter data structure.
542 * datain - TRUE if data read.
543 * length - Number of bytes to transfer.
544 *
545 * Returns: Nothing.
546 *
547 ****************************************************************/
548static void AtapiBusMaster (PADAPTER2220I padapter, UCHAR datain, ULONG length)
549 {
550 outl (padapter->timingAddress, padapter->regDmaAddrLoc);
551 outl (padapter->kBufferDma, padapter->regDmaAddrPci);
552 outl (length, padapter->regDmaCount);
553 if ( datain )
554 {
555 if ( padapter->readCount )
556 WalkScatGath (padapter, TRUE, padapter->readCount);
557 outb_p (0x08, padapter->regDmaDesc); // read operation
558 outb_p (0x08, padapter->regDmaMode); // no interrupt
559 padapter->readCount = length;
560 }
561 else
562 {
563 outb_p (0x00, padapter->regDmaDesc); // write operation
564 outb_p (0x08, padapter->regDmaMode); // no interrupt
565 if ( !padapter->atapiSpecial )
566 WalkScatGath (padapter, FALSE, length);
567 }
568 outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear
569 }
570/****************************************************************
571 * Name: WriteData :LOCAL
572 *
573 * Description: Write data to device.
574 *
575 * Parameters: padapter - Pointer adapter data structure.
576 *
577 * Returns: TRUE if drive does not assert DRQ in time.
578 *
579 ****************************************************************/
580static int WriteData (PADAPTER2220I padapter)
581 {
582 ULONG zl;
583
584 if ( !WaitDrq (padapter) )
585 {
586 if ( padapter->timingPIO )
587 {
588 zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
589 WalkScatGath (padapter, FALSE, zl * BYTES_PER_SECTOR);
590 outsw (padapter->regData, padapter->kBuffer, zl * (BYTES_PER_SECTOR / 2));
591 padapter->sectorCount -= zl;
592 }
593 else
594 BusMaster (padapter, 0, 0);
595 return 0;
596 }
597 padapter->cmd = 0; // null out the command byte
598 return 1;
599 }
600/****************************************************************
601 * Name: WriteDataBoth :LOCAL
602 *
603 * Description: Write data to device.
604 *
605 * Parameters: padapter - Pointer to adapter structure.
606 * pdev - Pointer to device structure
607 *
608 * Returns: Index + 1 of drive not failed or zero for OK.
609 *
610 ****************************************************************/
611static int WriteDataBoth (PADAPTER2220I padapter, POUR_DEVICE pdev)
612 {
613 ULONG zl;
614 UCHAR status0, status1;
615
616 SelectSpigot (padapter, pdev->spigots[0]);
617 status0 = WaitDrq (padapter);
618 if ( !status0 )
619 {
620 SelectSpigot (padapter, pdev->spigots[1]);
621 status1 = WaitDrq (padapter);
622 if ( !status1 )
623 {
624 SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1] | padapter->bigD);
625 if ( padapter->timingPIO )
626 {
627 zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
628 WalkScatGath (padapter, FALSE, zl * BYTES_PER_SECTOR);
629 outsw (padapter->regData, padapter->kBuffer, zl * (BYTES_PER_SECTOR / 2));
630 padapter->sectorCount -= zl;
631 }
632 else
633 BusMaster (padapter, 0, 0);
634 return 0;
635 }
636 }
637 padapter->cmd = 0; // null out the command byte
638 if ( status0 )
639 return 2;
640 return 1;
641 }
642/****************************************************************
643 * Name: IdeCmd :LOCAL
644 *
645 * Description: Process an IDE command.
646 *
647 * Parameters: padapter - Pointer adapter data structure.
648 * pdev - Pointer to device.
649 *
650 * Returns: Zero if no error or status register contents on error.
651 *
652 ****************************************************************/
653static UCHAR IdeCmd (PADAPTER2220I padapter, POUR_DEVICE pdev)
654 {
655 UCHAR status;
656
657 SelectSpigot (padapter, pdev->spigot | padapter->bigD); // select the spigot
658 outb_p (pdev->byte6 | ((UCHAR *)(&padapter->startSector))[3], padapter->regLba24); // select the drive
659 status = WaitReady (padapter);
660 if ( !status )
661 {
662 outb_p (padapter->sectorCount, padapter->regSectCount);
663 outb_p (((UCHAR *)(&padapter->startSector))[0], padapter->regLba0);
664 outb_p (((UCHAR *)(&padapter->startSector))[1], padapter->regLba8);
665 outb_p (((UCHAR *)(&padapter->startSector))[2], padapter->regLba16);
666 padapter->expectingIRQ = TRUE;
667 WriteCommand (padapter, padapter->cmd);
668 return 0;
669 }
670
671 padapter->cmd = 0; // null out the command byte
672 return status;
673 }
674/****************************************************************
675 * Name: IdeCmdBoth :LOCAL
676 *
677 * Description: Process an IDE command to both drivers.
678 *
679 * Parameters: padapter - Pointer adapter data structure.
680 * pdev - Pointer to device structure
681 *
682 * Returns: Index + 1 of drive not failed or zero for OK.
683 *
684 ****************************************************************/
685static UCHAR IdeCmdBoth (PADAPTER2220I padapter, POUR_DEVICE pdev)
686 {
687 UCHAR status0;
688 UCHAR status1;
689
690 SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1]); // select the spigots
691 outb_p (padapter->pdev->byte6 | ((UCHAR *)(&padapter->startSector))[3], padapter->regLba24);// select the drive
692 SelectSpigot (padapter, pdev->spigots[0]);
693 status0 = WaitReady (padapter);
694 if ( !status0 )
695 {
696 SelectSpigot (padapter, pdev->spigots[1]);
697 status1 = WaitReady (padapter);
698 if ( !status1 )
699 {
700 SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1] | padapter->bigD);
701 outb_p (padapter->sectorCount, padapter->regSectCount);
702 outb_p (((UCHAR *)(&padapter->startSector))[0], padapter->regLba0);
703 outb_p (((UCHAR *)(&padapter->startSector))[1], padapter->regLba8);
704 outb_p (((UCHAR *)(&padapter->startSector))[2], padapter->regLba16);
705 padapter->expectingIRQ = TRUE;
706 WriteCommand (padapter, padapter->cmd);
707 return 0;
708 }
709 }
710 padapter->cmd = 0; // null out the command byte
711 if ( status0 )
712 return 2;
713 return 1;
714 }
715/****************************************************************
716 * Name: OpDone :LOCAL
717 *
718 * Description: Complete an operatoin done sequence.
719 *
720 * Parameters: padapter - Pointer to host data block.
721 * spigot - Spigot select code.
722 * device - Device byte code.
723 *
724 * Returns: Nothing.
725 *
726 ****************************************************************/
727static void OpDone (PADAPTER2220I padapter, ULONG result)
728 {
729 Scsi_Cmnd *SCpnt = padapter->SCpnt;
730
731 if ( padapter->reconPhase )
732 {
733 padapter->reconPhase = 0;
734 if ( padapter->SCpnt )
735 {
736 Pci2220i_QueueCommand (SCpnt, SCpnt->scsi_done);
737 }
738 else
739 {
740 if ( padapter->reconOn )
741 {
742 ReconTimerExpiry ((unsigned long)padapter);
743 }
744 }
745 }
746 else
747 {
748 padapter->cmd = 0;
749 padapter->SCpnt = NULL;
750 padapter->pdev = NULL;
751 SCpnt->result = result;
752 SCpnt->scsi_done (SCpnt);
753 if ( padapter->reconOn && !padapter->reconTimer.data )
754 {
755 padapter->reconTimer.expires = jiffies + (HZ / 4); // start in 1/4 second
756 padapter->reconTimer.data = (unsigned long)padapter;
757 add_timer (&padapter->reconTimer);
758 }
759 }
760 }
761/****************************************************************
762 * Name: InlineIdentify :LOCAL
763 *
764 * Description: Do an intline inquiry on a drive.
765 *
766 * Parameters: padapter - Pointer to host data block.
767 * spigot - Spigot select code.
768 * device - Device byte code.
769 *
770 * Returns: Last addressable sector or zero if none.
771 *
772 ****************************************************************/
773static ULONG InlineIdentify (PADAPTER2220I padapter, UCHAR spigot, UCHAR device)
774 {
775 PIDENTIFY_DATA pid = (PIDENTIFY_DATA)padapter->kBuffer;
776
777 SelectSpigot (padapter, spigot | SEL_IRQ_OFF); // select the spigot
778 outb_p ((device << 4) | 0xA0, padapter->regLba24); // select the drive
779 if ( WaitReady (padapter) )
780 return 0;
781 WriteCommand (padapter, IDE_COMMAND_IDENTIFY);
782 if ( WaitDrq (padapter) )
783 return 0;
784 insw (padapter->regData, padapter->kBuffer, sizeof (IDENTIFY_DATA) >> 1);
785 return (pid->LBATotalSectors - 1);
786 }
787/****************************************************************
788 * Name: AtapiIdentify :LOCAL
789 *
790 * Description: Do an intline inquiry on a drive.
791 *
792 * Parameters: padapter - Pointer to host data block.
793 * pdev - Pointer to device table.
794 *
795 * Returns: TRUE on error.
796 *
797 ****************************************************************/
798static ULONG AtapiIdentify (PADAPTER2220I padapter, POUR_DEVICE pdev)
799 {
800 ATAPI_GENERAL_0 ag0;
801 USHORT zs;
802 int z;
803
804 AtapiDevice (padapter, pdev->byte6);
805 WriteCommand (padapter, IDE_COMMAND_ATAPI_IDENTIFY);
806 if ( AtapiWaitDrq (padapter, 3000) )
807 return TRUE;
808
809 *(USHORT *)&ag0 = inw_p (padapter->regData);
810 for ( z = 0; z < 255; z++ )
811 zs = inw_p (padapter->regData);
812
813 if ( ag0.ProtocolType == 2 )
814 {
815 if ( ag0.CmdDrqType == 1 )
816 pdev->cmdDrqInt = TRUE;
817 switch ( ag0.CmdPacketSize )
818 {
819 case 0:
820 pdev->packet = 6;
821 break;
822 case 1:
823 pdev->packet = 8;
824 break;
825 default:
826 pdev->packet = 6;
827 break;
828 }
829 return FALSE;
830 }
831 return TRUE;
832 }
833/****************************************************************
834 * Name: Atapi2Scsi
835 *
836 * Description: Convert ATAPI data to SCSI data.
837 *
838 * Parameters: padapter - Pointer adapter data structure.
839 * SCpnt - Pointer to SCSI command structure.
840 *
841 * Returns: Nothing.
842 *
843 ****************************************************************/
844void Atapi2Scsi (PADAPTER2220I padapter, Scsi_Cmnd *SCpnt)
845 {
846 UCHAR *buff = padapter->currentSgBuffer;
847
848 switch ( SCpnt->cmnd[0] )
849 {
850 case SCSIOP_MODE_SENSE:
851 buff[0] = padapter->kBuffer[1];
852 buff[1] = padapter->kBuffer[2];
853 buff[2] = padapter->kBuffer[3];
854 buff[3] = padapter->kBuffer[7];
855 memcpy (&buff[4], &padapter->kBuffer[8], padapter->atapiCdb[8] - 8);
856 break;
857 case SCSIOP_INQUIRY:
858 padapter->kBuffer[2] = 2;
859 memcpy (buff, padapter->kBuffer, padapter->currentSgCount);
860 break;
861 default:
862 if ( padapter->readCount )
863 WalkScatGath (padapter, TRUE, padapter->readCount);
864 break;
865 }
866 }
867/****************************************************************
868 * Name: Scsi2Atapi
869 *
870 * Description: Convert SCSI packet command to Atapi packet command.
871 *
872 * Parameters: padapter - Pointer adapter data structure.
873 * SCpnt - Pointer to SCSI command structure.
874 *
875 * Returns: Nothing.
876 *
877 ****************************************************************/
878static void Scsi2Atapi (PADAPTER2220I padapter, Scsi_Cmnd *SCpnt)
879 {
880 UCHAR *cdb = SCpnt->cmnd;
881 UCHAR *buff = padapter->currentSgBuffer;
882
883 switch (cdb[0])
884 {
885 case SCSIOP_READ6:
886 padapter->atapiCdb[0] = SCSIOP_READ;
887 padapter->atapiCdb[1] = cdb[1] & 0xE0;
888 padapter->atapiCdb[3] = cdb[1] & 0x1F;
889 padapter->atapiCdb[4] = cdb[2];
890 padapter->atapiCdb[5] = cdb[3];
891 padapter->atapiCdb[8] = cdb[4];
892 padapter->atapiCdb[9] = cdb[5];
893 break;
894 case SCSIOP_WRITE6:
895 padapter->atapiCdb[0] = SCSIOP_WRITE;
896 padapter->atapiCdb[1] = cdb[1] & 0xE0;
897 padapter->atapiCdb[3] = cdb[1] & 0x1F;
898 padapter->atapiCdb[4] = cdb[2];
899 padapter->atapiCdb[5] = cdb[3];
900 padapter->atapiCdb[8] = cdb[4];
901 padapter->atapiCdb[9] = cdb[5];
902 break;
903 case SCSIOP_MODE_SENSE:
904 padapter->atapiCdb[0] = SCSIOP_MODE_SENSE10;
905 padapter->atapiCdb[2] = cdb[2];
906 padapter->atapiCdb[8] = cdb[4] + 4;
907 break;
908
909 case SCSIOP_MODE_SELECT:
910 padapter->atapiSpecial = TRUE;
911 padapter->atapiCdb[0] = SCSIOP_MODE_SELECT10;
912 padapter->atapiCdb[1] = cdb[1] | 0x10;
913 memcpy (padapter->kBuffer, buff, 4);
914 padapter->kBuffer[4] = padapter->kBuffer[5] = 0;
915 padapter->kBuffer[6] = padapter->kBuffer[7] = 0;
916 memcpy (&padapter->kBuffer[8], &buff[4], cdb[4] - 4);
917 padapter->atapiCdb[8] = cdb[4] + 4;
918 break;
919 }
920 }
921/****************************************************************
922 * Name: AtapiSendCdb
923 *
924 * Description: Send the CDB packet to the device.
925 *
926 * Parameters: padapter - Pointer adapter data structure.
927 * pdev - Pointer to device.
928 * cdb - Pointer to 16 byte SCSI cdb.
929 *
930 * Returns: Nothing.
931 *
932 ****************************************************************/
933static void AtapiSendCdb (PADAPTER2220I padapter, POUR_DEVICE pdev, CHAR *cdb)
934 {
935 DEB (printk ("\nPCI2242I: CDB: %X %X %X %X %X %X %X %X %X %X %X %X", cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]));
936 outsw (padapter->regData, cdb, pdev->packet);
937 }
938/****************************************************************
939 * Name: AtapiRequestSense
940 *
941 * Description: Send the CDB packet to the device.
942 *
943 * Parameters: padapter - Pointer adapter data structure.
944 * pdev - Pointer to device.
945 * SCpnt - Pointer to SCSI command structure.
946 * pass - If true then this is the second pass to send cdb.
947 *
948 * Returns: TRUE on error.
949 *
950 ****************************************************************/
951static int AtapiRequestSense (PADAPTER2220I padapter, POUR_DEVICE pdev, Scsi_Cmnd *SCpnt, UCHAR pass)
952 {
953 UCHAR cdb[16] = {SCSIOP_REQUEST_SENSE,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0};
954
955 DEB (printk ("\nPCI2242I: AUTO REQUEST SENSE"));
956 cdb[4] = (UCHAR)(sizeof (SCpnt->sense_buffer));
957 if ( !pass )
958 {
959 padapter->reqSense = TRUE;
960 AtapiCountLo (padapter, cdb[4]);
961 AtapiCountHi (padapter, 0);
962 outb_p (0, padapter->regError);
963 WriteCommand (padapter, IDE_COMMAND_ATAPI_PACKET);
964 if ( pdev->cmdDrqInt )
965 return FALSE;
966
967 if ( AtapiWaitDrq (padapter, 500) )
968 return TRUE;
969 }
970 AtapiSendCdb (padapter, pdev, cdb);
971 return FALSE;
972 }
973/****************************************************************
974 * Name: InlineReadSignature :LOCAL
975 *
976 * Description: Do an inline read RAID sigature.
977 *
978 * Parameters: padapter - Pointer adapter data structure.
979 * pdev - Pointer to device.
980 * index - index of data to read.
981 *
982 * Returns: Zero if no error or status register contents on error.
983 *
984 ****************************************************************/
985static UCHAR InlineReadSignature (PADAPTER2220I padapter, POUR_DEVICE pdev, int index)
986 {
987 UCHAR status;
988 ULONG zl = pdev->lastsectorlba[index];
989
990 SelectSpigot (padapter, pdev->spigots[index] | SEL_IRQ_OFF); // select the spigot without interrupts
991 outb_p (pdev->byte6 | ((UCHAR *)&zl)[3], padapter->regLba24);
992 status = WaitReady (padapter);
993 if ( !status )
994 {
995 outb_p (((UCHAR *)&zl)[2], padapter->regLba16);
996 outb_p (((UCHAR *)&zl)[1], padapter->regLba8);
997 outb_p (((UCHAR *)&zl)[0], padapter->regLba0);
998 outb_p (1, padapter->regSectCount);
999 WriteCommand (padapter, IDE_COMMAND_READ);
1000 status = WaitDrq (padapter);
1001 if ( !status )
1002 {
1003 insw (padapter->regData, padapter->kBuffer, BYTES_PER_SECTOR / 2);
1004 ((ULONG *)(&pdev->DiskMirror[index]))[0] = ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[0];
1005 ((ULONG *)(&pdev->DiskMirror[index]))[1] = ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[1];
1006 // some drives assert DRQ before IRQ so let's make sure we clear the IRQ
1007 WaitReady (padapter);
1008 return 0;
1009 }
1010 }
1011 return status;
1012 }
1013/****************************************************************
1014 * Name: DecodeError :LOCAL
1015 *
1016 * Description: Decode and process device errors.
1017 *
1018 * Parameters: padapter - Pointer to adapter data.
1019 * status - Status register code.
1020 *
1021 * Returns: The driver status code.
1022 *
1023 ****************************************************************/
1024static ULONG DecodeError (PADAPTER2220I padapter, UCHAR status)
1025 {
1026 UCHAR error;
1027
1028 padapter->expectingIRQ = 0;
1029 if ( status & IDE_STATUS_WRITE_FAULT )
1030 {
1031 return DID_PARITY << 16;
1032 }
1033 if ( status & IDE_STATUS_BUSY )
1034 return DID_BUS_BUSY << 16;
1035
1036 error = inb_p (padapter->regError);
1037 DEB(printk ("\npci2220i error register: %x", error));
1038 switch ( error )
1039 {
1040 case IDE_ERROR_AMNF:
1041 case IDE_ERROR_TKONF:
1042 case IDE_ERROR_ABRT:
1043 case IDE_ERROR_IDFN:
1044 case IDE_ERROR_UNC:
1045 case IDE_ERROR_BBK:
1046 default:
1047 return DID_ERROR << 16;
1048 }
1049 return DID_ERROR << 16;
1050 }
1051/****************************************************************
1052 * Name: StartTimer :LOCAL
1053 *
1054 * Description: Start the timer.
1055 *
1056 * Parameters: ipadapter - Pointer adapter data structure.
1057 *
1058 * Returns: Nothing.
1059 *
1060 ****************************************************************/
1061static void StartTimer (PADAPTER2220I padapter)
1062 {
1063 padapter->timer.expires = jiffies + TIMEOUT_DATA;
1064 add_timer (&padapter->timer);
1065 }
1066/****************************************************************
1067 * Name: WriteSignature :LOCAL
1068 *
1069 * Description: Start the timer.
1070 *
1071 * Parameters: padapter - Pointer adapter data structure.
1072 * pdev - Pointer to our device.
1073 * spigot - Selected spigot.
1074 * index - index of mirror signature on device.
1075 *
1076 * Returns: TRUE on any error.
1077 *
1078 ****************************************************************/
1079static int WriteSignature (PADAPTER2220I padapter, POUR_DEVICE pdev, UCHAR spigot, int index)
1080 {
1081 ULONG zl;
1082
1083 SelectSpigot (padapter, spigot);
1084 zl = pdev->lastsectorlba[index];
1085 outb_p (pdev->byte6 | ((UCHAR *)&zl)[3], padapter->regLba24);
1086 outb_p (((UCHAR *)&zl)[2], padapter->regLba16);
1087 outb_p (((UCHAR *)&zl)[1], padapter->regLba8);
1088 outb_p (((UCHAR *)&zl)[0], padapter->regLba0);
1089 outb_p (1, padapter->regSectCount);
1090
1091 WriteCommand (padapter, IDE_COMMAND_WRITE);
1092 if ( WaitDrq (padapter) )
1093 return TRUE;
1094 StartTimer (padapter);
1095 padapter->expectingIRQ = TRUE;
1096
1097 ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[0] = ((ULONG *)(&pdev->DiskMirror[index]))[0];
1098 ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[1] = ((ULONG *)(&pdev->DiskMirror[index]))[1];
1099 outsw (padapter->regData, padapter->kBuffer, BYTES_PER_SECTOR / 2);
1100 return FALSE;
1101 }
1102/*******************************************************************************************************
1103 * Name: InitFailover
1104 *
1105 * Description: This is the beginning of the failover routine
1106 *
1107 * Parameters: SCpnt - Pointer to SCSI command structure.
1108 * padapter - Pointer adapter data structure.
1109 * pdev - Pointer to our device.
1110 *
1111 * Returns: TRUE on error.
1112 *
1113 ******************************************************************************************************/
1114static int InitFailover (PADAPTER2220I padapter, POUR_DEVICE pdev)
1115 {
1116 UCHAR spigot;
1117
1118 DEB (printk ("\npci2220i: Initialize failover process - survivor = %d", pdev->deviceID[padapter->survivor]));
1119 pdev->raid = FALSE; //initializes system for non raid mode
1120 pdev->reconOn = FALSE;
1121 spigot = pdev->spigots[padapter->survivor];
1122
1123 if ( pdev->DiskMirror[padapter->survivor].status & UCBF_REBUILD )
1124 {
1125 DEB (printk ("\n failed, is survivor"));
1126 return (TRUE);
1127 }
1128
1129 if ( HardReset (padapter, pdev, spigot) )
1130 {
1131 DEB (printk ("\n failed, reset"));
1132 return TRUE;
1133 }
1134
1135 Alarm (padapter, pdev->deviceID[padapter->survivor ^ 1]);
1136 pdev->DiskMirror[padapter->survivor].status = UCBF_MIRRORED | UCBF_SURVIVOR; //clear present status
1137
1138 if ( WriteSignature (padapter, pdev, spigot, padapter->survivor) )
1139 {
1140 DEB (printk ("\n failed, write signature"));
1141 return TRUE;
1142 }
1143 padapter->failinprog = TRUE;
1144 return FALSE;
1145 }
1146/****************************************************************
1147 * Name: TimerExpiry :LOCAL
1148 *
1149 * Description: Timer expiry routine.
1150 *
1151 * Parameters: data - Pointer adapter data structure.
1152 *
1153 * Returns: Nothing.
1154 *
1155 ****************************************************************/
1156static void TimerExpiry (unsigned long data)
1157 {
1158 PADAPTER2220I padapter = (PADAPTER2220I)data;
1159 struct Scsi_Host *host = padapter->SCpnt->device->host;
1160 POUR_DEVICE pdev = padapter->pdev;
1161 UCHAR status = IDE_STATUS_BUSY;
1162 UCHAR temp, temp1;
1163 unsigned long flags;
1164
1165 /*
1166 * Disable interrupts, if they aren't already disabled and acquire
1167 * the I/O spinlock.
1168 */
1169 spin_lock_irqsave (host->host_lock, flags);
1170 DEB (printk ("\nPCI2220I: Timeout expired "));
1171
1172 if ( padapter->failinprog )
1173 {
1174 DEB (printk ("in failover process"));
1175 OpDone (padapter, DecodeError (padapter, inb_p (padapter->regStatCmd)));
1176 goto timerExpiryDone;
1177 }
1178
1179 while ( padapter->reconPhase )
1180 {
1181 DEB (printk ("in recon phase %X", padapter->reconPhase));
1182 switch ( padapter->reconPhase )
1183 {
1184 case RECON_PHASE_MARKING:
1185 case RECON_PHASE_LAST:
1186 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 1 : 0;
1187 DEB (printk ("\npci2220i: FAILURE 1"));
1188 if ( InitFailover (padapter, pdev) )
1189 OpDone (padapter, DID_ERROR << 16);
1190 goto timerExpiryDone;
1191
1192 case RECON_PHASE_READY:
1193 OpDone (padapter, DID_ERROR << 16);
1194 goto timerExpiryDone;
1195
1196 case RECON_PHASE_COPY:
1197 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
1198 DEB (printk ("\npci2220i: FAILURE 2"));
1199 DEB (printk ("\n spig/stat = %X", inb_p (padapter->regStatSel));
1200 if ( InitFailover (padapter, pdev) )
1201 OpDone (padapter, DID_ERROR << 16);
1202 goto timerExpiryDone;
1203
1204 case RECON_PHASE_UPDATE:
1205 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
1206 DEB (printk ("\npci2220i: FAILURE 3")));
1207 if ( InitFailover (padapter, pdev) )
1208 OpDone (padapter, DID_ERROR << 16);
1209 goto timerExpiryDone;
1210
1211 case RECON_PHASE_END:
1212 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
1213 DEB (printk ("\npci2220i: FAILURE 4"));
1214 if ( InitFailover (padapter, pdev) )
1215 OpDone (padapter, DID_ERROR << 16);
1216 goto timerExpiryDone;
1217
1218 default:
1219 goto timerExpiryDone;
1220 }
1221 }
1222
1223 while ( padapter->cmd )
1224 {
1225 outb_p (0x08, padapter->regDmaCmdStat); // cancel interrupt from DMA engine
1226 if ( pdev->raid )
1227 {
1228 if ( padapter->cmd == WRITE_CMD )
1229 {
1230 DEB (printk ("in RAID write operation"));
1231 temp = ( pdev->spigot & (SEL_1 | SEL_2) ) ? SEL_1 : SEL_3;
1232 if ( inb_p (padapter->regStatSel) & temp )
1233 {
1234 DEB (printk ("\npci2220i: Determined A OK"));
1235 SelectSpigot (padapter, temp | SEL_IRQ_OFF); // Masking the interrupt during spigot select
1236 temp = inb_p (padapter->regStatCmd);
1237 }
1238 else
1239 temp = IDE_STATUS_BUSY;
1240
1241 temp1 = ( pdev->spigot & (SEL_1 | SEL_2) ) ? SEL_2 : SEL_4;
1242 if ( inb (padapter->regStatSel) & temp1 )
1243 {
1244 DEB (printk ("\npci2220i: Determined B OK"));
1245 SelectSpigot (padapter, temp1 | SEL_IRQ_OFF); // Masking the interrupt during spigot select
1246 temp1 = inb_p (padapter->regStatCmd);
1247 }
1248 else
1249 temp1 = IDE_STATUS_BUSY;
1250
1251 if ( (temp & IDE_STATUS_BUSY) || (temp1 & IDE_STATUS_BUSY) )
1252 {
1253 DEB (printk ("\npci2220i: Status A: %X B: %X", temp & 0xFF, temp1 & 0xFF));
1254 if ( (temp & IDE_STATUS_BUSY) && (temp1 & IDE_STATUS_BUSY) )
1255 {
1256 status = temp;
1257 break;
1258 }
1259 else
1260 {
1261 if ( temp & IDE_STATUS_BUSY )
1262 padapter->survivor = 1;
1263 else
1264 padapter->survivor = 0;
1265 if ( InitFailover (padapter, pdev) )
1266 {
1267 status = inb_p (padapter->regStatCmd);
1268 break;
1269 }
1270 goto timerExpiryDone;
1271 }
1272 }
1273 }
1274 else
1275 {
1276 DEB (printk ("in RAID read operation"));
1277 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
1278 DEB (printk ("\npci2220i: FAILURE 6"));
1279 if ( InitFailover (padapter, pdev) )
1280 {
1281 status = inb_p (padapter->regStatCmd);
1282 break;
1283 }
1284 goto timerExpiryDone;
1285 }
1286 }
1287 else
1288 {
1289 DEB (printk ("in I/O operation"));
1290 status = inb_p (padapter->regStatCmd);
1291 }
1292 break;
1293 }
1294
1295 OpDone (padapter, DecodeError (padapter, status));
1296
1297timerExpiryDone:;
1298 /*
1299 * Release the I/O spinlock and restore the original flags
1300 * which will enable interrupts if and only if they were
1301 * enabled on entry.
1302 */
1303 spin_unlock_irqrestore (host->host_lock, flags);
1304 }
1305/****************************************************************
1306 * Name: SetReconstruct :LOCAL
1307 *
1308 * Description: Set the reconstruct up.
1309 *
1310 * Parameters: pdev - Pointer to device structure.
1311 * index - Mirror index number.
1312 *
1313 * Returns: Number of sectors on new disk required.
1314 *
1315 ****************************************************************/
1316static LONG SetReconstruct (POUR_DEVICE pdev, int index)
1317 {
1318 pdev->DiskMirror[index].status = UCBF_MIRRORED; // setup the flags
1319 pdev->DiskMirror[index ^ 1].status = UCBF_MIRRORED | UCBF_REBUILD;
1320 pdev->DiskMirror[index ^ 1].reconstructPoint = 0; // start the reconstruct
1321 pdev->reconCount = 1990; // mark target drive early
1322 return pdev->DiskMirror[index].reconstructPoint;
1323 }
1324/****************************************************************
1325 * Name: ReconTimerExpiry :LOCAL
1326 *
1327 * Description: Reconstruct timer expiry routine.
1328 *
1329 * Parameters: data - Pointer adapter data structure.
1330 *
1331 * Returns: Nothing.
1332 *
1333 ****************************************************************/
1334static void ReconTimerExpiry (unsigned long data)
1335 {
1336 PADAPTER2220I padapter = (PADAPTER2220I)data;
1337 struct Scsi_Host *host = padapter->SCpnt->device->host;
1338 POUR_DEVICE pdev;
1339 ULONG testsize = 0;
1340 PIDENTIFY_DATA pid;
1341 USHORT minmode;
1342 ULONG zl;
1343 UCHAR zc;
1344 USHORT z;
1345 unsigned long flags;
1346
1347 /*
1348 * Disable interrupts, if they aren't already disabled and acquire
1349 * the I/O spinlock.
1350 */
1351 spin_lock_irqsave(host->host_lock, flags);
1352
1353 if ( padapter->SCpnt )
1354 goto reconTimerExpiry;
1355
1356 padapter->reconTimer.data = 0;
1357 for ( z = padapter->devInReconIndex + 1; z < BIGD_MAXDRIVES; z++ )
1358 {
1359 if ( padapter->device[z].reconOn )
1360 break;
1361 }
1362 if ( z < BIGD_MAXDRIVES )
1363 pdev = &padapter->device[z];
1364 else
1365 {
1366 for ( z = 0; z < BIGD_MAXDRIVES; z++ )
1367 {
1368 if ( padapter->device[z].reconOn )
1369 break;
1370 }
1371 if ( z < BIGD_MAXDRIVES )
1372 pdev = &padapter->device[z];
1373 else
1374 {
1375 padapter->reconOn = FALSE;
1376 goto reconTimerExpiry;
1377 }
1378 }
1379
1380 padapter->devInReconIndex = z;
1381 pid = (PIDENTIFY_DATA)padapter->kBuffer;
1382 padapter->pdev = pdev;
1383 if ( pdev->reconIsStarting )
1384 {
1385 pdev->reconIsStarting = FALSE;
1386 pdev->reconOn = FALSE;
1387
1388 while ( (pdev->DiskMirror[0].signature == SIGNATURE) && (pdev->DiskMirror[1].signature == SIGNATURE) &&
1389 (pdev->DiskMirror[0].pairIdentifier == (pdev->DiskMirror[1].pairIdentifier ^ 1)) )
1390 {
1391 if ( (pdev->DiskMirror[0].status & UCBF_MATCHED) && (pdev->DiskMirror[1].status & UCBF_MATCHED) )
1392 break;
1393
1394 if ( pdev->DiskMirror[0].status & UCBF_SURVIVOR ) // is first drive survivor?
1395 testsize = SetReconstruct (pdev, 0);
1396 else
1397 if ( pdev->DiskMirror[1].status & UCBF_SURVIVOR ) // is second drive survivor?
1398 testsize = SetReconstruct (pdev, 1);
1399
1400 if ( (pdev->DiskMirror[0].status & UCBF_REBUILD) || (pdev->DiskMirror[1].status & UCBF_REBUILD) )
1401 {
1402 if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
1403 pdev->mirrorRecon = 0;
1404 else
1405 pdev->mirrorRecon = 1;
1406 pdev->reconOn = TRUE;
1407 }
1408 break;
1409 }
1410
1411 if ( !pdev->reconOn )
1412 goto reconTimerExpiry;
1413
1414 if ( padapter->bigD )
1415 {
1416 padapter->failRegister = 0;
1417 outb_p (~padapter->failRegister, padapter->regFail);
1418 }
1419 else
1420 {
1421 zc = ((inb_p (padapter->regStatSel) >> 3) | inb_p (padapter->regStatSel)) & 0x83; // mute the alarm
1422 outb_p (0xFF, padapter->regFail);
1423 }
1424
1425 while ( 1 )
1426 {
1427 DEB (printk ("\npci2220i: hard reset issue"));
1428 if ( HardReset (padapter, pdev, pdev->spigots[pdev->mirrorRecon]) )
1429 {
1430 DEB (printk ("\npci2220i: sub 1"));
1431 break;
1432 }
1433
1434 pdev->lastsectorlba[pdev->mirrorRecon] = InlineIdentify (padapter, pdev->spigots[pdev->mirrorRecon], pdev->deviceID[pdev->mirrorRecon] & 1);
1435
1436 if ( pdev->lastsectorlba[pdev->mirrorRecon] < testsize )
1437 {
1438 DEB (printk ("\npci2220i: sub 2 %ld %ld", pdev->lastsectorlba[pdev->mirrorRecon], testsize));
1439 break;
1440 }
1441
1442 // test LBA and multiper sector transfer compatibility
1443 if (!pid->SupportLBA || (pid->NumSectorsPerInt < SECTORSXFER) || !pid->Valid_64_70 )
1444 {
1445 DEB (printk ("\npci2220i: sub 3"));
1446 break;
1447 }
1448
1449 // test PIO/bus matering mode compatibility
1450 if ( (pid->MinPIOCycleWithoutFlow > 240) && !pid->SupportIORDYDisable && !padapter->timingPIO )
1451 {
1452 DEB (printk ("\npci2220i: sub 4"));
1453 break;
1454 }
1455
1456 if ( pid->MinPIOCycleWithoutFlow <= 120 ) // setup timing mode of drive
1457 minmode = 5;
1458 else
1459 {
1460 if ( pid->MinPIOCylceWithFlow <= 150 )
1461 minmode = 4;
1462 else
1463 {
1464 if ( pid->MinPIOCylceWithFlow <= 180 )
1465 minmode = 3;
1466 else
1467 {
1468 if ( pid->MinPIOCylceWithFlow <= 240 )
1469 minmode = 2;
1470 else
1471 {
1472 DEB (printk ("\npci2220i: sub 5"));
1473 break;
1474 }
1475 }
1476 }
1477 }
1478
1479 if ( padapter->timingMode > minmode ) // set minimum timing mode
1480 padapter->timingMode = minmode;
1481 if ( padapter->timingMode >= 2 )
1482 padapter->timingAddress = ModeArray[padapter->timingMode - 2];
1483 else
1484 padapter->timingPIO = TRUE;
1485
1486 padapter->reconOn = TRUE;
1487 break;
1488 }
1489
1490 if ( !pdev->reconOn )
1491 {
1492 padapter->survivor = pdev->mirrorRecon ^ 1;
1493 padapter->reconPhase = RECON_PHASE_FAILOVER;
1494 DEB (printk ("\npci2220i: FAILURE 7"));
1495 InitFailover (padapter, pdev);
1496 goto reconTimerExpiry;
1497 }
1498
1499 pdev->raid = TRUE;
1500
1501 if ( WriteSignature (padapter, pdev, pdev->spigot, pdev->mirrorRecon ^ 1) )
1502 goto reconTimerExpiry;
1503 padapter->reconPhase = RECON_PHASE_MARKING;
1504 goto reconTimerExpiry;
1505 }
1506
1507 //**********************************
1508 // reconstruct copy starts here
1509 //**********************************
1510 if ( pdev->reconCount++ > 2000 )
1511 {
1512 pdev->reconCount = 0;
1513 if ( WriteSignature (padapter, pdev, pdev->spigots[pdev->mirrorRecon], pdev->mirrorRecon) )
1514 {
1515 padapter->survivor = pdev->mirrorRecon ^ 1;
1516 padapter->reconPhase = RECON_PHASE_FAILOVER;
1517 DEB (printk ("\npci2220i: FAILURE 8"));
1518 InitFailover (padapter, pdev);
1519 goto reconTimerExpiry;
1520 }
1521 padapter->reconPhase = RECON_PHASE_UPDATE;
1522 goto reconTimerExpiry;
1523 }
1524
1525 zl = pdev->DiskMirror[pdev->mirrorRecon].reconstructPoint;
1526 padapter->reconSize = pdev->DiskMirror[pdev->mirrorRecon ^ 1].reconstructPoint - zl;
1527 if ( padapter->reconSize > MAX_BUS_MASTER_BLOCKS )
1528 padapter->reconSize = MAX_BUS_MASTER_BLOCKS;
1529
1530 if ( padapter->reconSize )
1531 {
1532 SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1]); // select the spigots
1533 outb_p (pdev->byte6 | ((UCHAR *)(&zl))[3], padapter->regLba24); // select the drive
1534 SelectSpigot (padapter, pdev->spigot);
1535 if ( WaitReady (padapter) )
1536 goto reconTimerExpiry;
1537
1538 SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon]);
1539 if ( WaitReady (padapter) )
1540 {
1541 padapter->survivor = pdev->mirrorRecon ^ 1;
1542 padapter->reconPhase = RECON_PHASE_FAILOVER;
1543 DEB (printk ("\npci2220i: FAILURE 9"));
1544 InitFailover (padapter, pdev);
1545 goto reconTimerExpiry;
1546 }
1547
1548 SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1]);
1549 outb_p (padapter->reconSize & 0xFF, padapter->regSectCount);
1550 outb_p (((UCHAR *)(&zl))[0], padapter->regLba0);
1551 outb_p (((UCHAR *)(&zl))[1], padapter->regLba8);
1552 outb_p (((UCHAR *)(&zl))[2], padapter->regLba16);
1553 padapter->expectingIRQ = TRUE;
1554 padapter->reconPhase = RECON_PHASE_READY;
1555 SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon]);
1556 WriteCommand (padapter, WRITE_CMD);
1557 StartTimer (padapter);
1558 SelectSpigot (padapter, pdev->spigot);
1559 WriteCommand (padapter, READ_CMD);
1560 goto reconTimerExpiry;
1561 }
1562
1563 pdev->DiskMirror[pdev->mirrorRecon].status = UCBF_MIRRORED | UCBF_MATCHED;
1564 pdev->DiskMirror[pdev->mirrorRecon ^ 1].status = UCBF_MIRRORED | UCBF_MATCHED;
1565 if ( WriteSignature (padapter, pdev, pdev->spigot, pdev->mirrorRecon ^ 1) )
1566 goto reconTimerExpiry;
1567 padapter->reconPhase = RECON_PHASE_LAST;
1568
1569reconTimerExpiry:;
1570 /*
1571 * Release the I/O spinlock and restore the original flags
1572 * which will enable interrupts if and only if they were
1573 * enabled on entry.
1574 */
1575 spin_unlock_irqrestore(host->host_lock, flags);
1576 }
1577/****************************************************************
1578 * Name: Irq_Handler :LOCAL
1579 *
1580 * Description: Interrupt handler.
1581 *
1582 * Parameters: irq - Hardware IRQ number.
1583 * dev_id -
1584 * regs -
1585 *
1586 * Returns: TRUE if drive is not ready in time.
1587 *
1588 ****************************************************************/
1589static irqreturn_t Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
1590 {
1591 struct Scsi_Host *shost = NULL; // Pointer to host data block
1592 PADAPTER2220I padapter; // Pointer to adapter control structure
1593 POUR_DEVICE pdev;
1594 Scsi_Cmnd *SCpnt;
1595 UCHAR status;
1596 UCHAR status1;
1597 ATAPI_STATUS statusa;
1598 ATAPI_REASON reasona;
1599 ATAPI_ERROR errora;
1600 int z;
1601 ULONG zl;
1602 unsigned long flags;
1603 int handled = 0;
1604
1605// DEB (printk ("\npci2220i received interrupt\n"));
1606
1607 for ( z = 0; z < NumAdapters; z++ ) // scan for interrupt to process
1608 {
1609 if ( PsiHost[z]->irq == (UCHAR)(irq & 0xFF) )
1610 {
1611 if ( inw_p (HOSTDATA(PsiHost[z])->regIrqControl) & 0x8000 )
1612 {
1613 shost = PsiHost[z];
1614 break;
1615 }
1616 }
1617 }
1618
1619 if ( !shost )
1620 {
1621 DEB (printk ("\npci2220i: not my interrupt"));
1622 goto out;
1623 }
1624
1625 handled = 1;
1626 spin_lock_irqsave(shost->host_lock, flags);
1627 padapter = HOSTDATA(shost);
1628 pdev = padapter->pdev;
1629 SCpnt = padapter->SCpnt;
1630 outb_p (0x08, padapter->regDmaCmdStat); // cancel interrupt from DMA engine
1631
1632 if ( padapter->atapi && SCpnt )
1633 {
1634 *(char *)&statusa = inb_p (padapter->regStatCmd); // read the device status
1635 *(char *)&reasona = inb_p (padapter->regSectCount); // read the device interrupt reason
1636
1637 if ( !statusa.bsy )
1638 {
1639 if ( statusa.drq ) // test for transfer phase
1640 {
1641 if ( !reasona.cod ) // test for data phase
1642 {
1643 z = (ULONG)inb_p (padapter->regLba8) | (ULONG)(inb_p (padapter->regLba16) << 8);
1644 if ( padapter->reqSense )
1645 insw (padapter->regData, SCpnt->sense_buffer, z / 2);
1646 else
1647 AtapiBusMaster (padapter, reasona.io, z);
1648 goto irq_return;
1649 }
1650 if ( reasona.cod && !reasona.io ) // test for command packet phase
1651 {
1652 if ( padapter->reqSense )
1653 AtapiRequestSense (padapter, pdev, SCpnt, TRUE);
1654 else
1655 AtapiSendCdb (padapter, pdev, padapter->atapiCdb);
1656 goto irq_return;
1657 }
1658 }
1659 else
1660 {
1661 if ( reasona.io && statusa.drdy ) // test for status phase
1662 {
1663 Atapi2Scsi (padapter, SCpnt);
1664 if ( statusa.check )
1665 {
1666 *(UCHAR *)&errora = inb_p (padapter->regError); // read the device error
1667 if ( errora.senseKey )
1668 {
1669 if ( padapter->reqSense || AtapiRequestSense (padapter, pdev, SCpnt, FALSE) )
1670 OpDone (padapter, DID_ERROR << 16);
1671 }
1672 else
1673 {
1674 if ( errora.ili || errora.abort )
1675 OpDone (padapter, DID_ERROR << 16);
1676 else
1677 OpDone (padapter, DID_OK << 16);
1678 }
1679 }
1680 else
1681 if ( padapter->reqSense )
1682 {
1683 DEB (printk ("PCI2242I: Sense codes - %X %X %X ", ((UCHAR *)SCpnt->sense_buffer)[0], ((UCHAR *)SCpnt->sense_buffer)[12], ((UCHAR *)SCpnt->sense_buffer)[13]));
1684 OpDone (padapter, (DRIVER_SENSE << 24) | (DID_OK << 16) | 2);
1685 }
1686 else
1687 OpDone (padapter, DID_OK << 16);
1688 }
1689 }
1690 }
1691 goto irq_return;
1692 }
1693
1694 if ( !padapter->expectingIRQ || !(SCpnt || padapter->reconPhase) )
1695 {
1696 DEB(printk ("\npci2220i Unsolicited interrupt\n"));
1697 STOP_HERE ();
1698 goto irq_return;
1699 }
1700 padapter->expectingIRQ = 0;
1701
1702 if ( padapter->failinprog )
1703 {
1704 DEB (printk ("\npci2220i interrupt failover complete"));
1705 padapter->failinprog = FALSE;
1706 status = inb_p (padapter->regStatCmd); // read the device status
1707 if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
1708 {
1709 DEB (printk ("\npci2220i: interrupt failover error from drive %X", status));
1710 padapter->cmd = 0;
1711 }
1712 else
1713 {
1714 DEB (printk ("\npci2220i: restarting failed opertation."));
1715 pdev->spigot = (padapter->survivor) ? pdev->spigots[1] : pdev->spigots[0];
1716 del_timer (&padapter->timer);
1717 if ( padapter->reconPhase )
1718 OpDone (padapter, DID_OK << 16);
1719 else
1720 Pci2220i_QueueCommand (SCpnt, SCpnt->scsi_done);
1721 goto irq_return;
1722 }
1723 }
1724
1725 if ( padapter->reconPhase )
1726 {
1727 switch ( padapter->reconPhase )
1728 {
1729 case RECON_PHASE_MARKING:
1730 case RECON_PHASE_LAST:
1731 status = inb_p (padapter->regStatCmd); // read the device status
1732 del_timer (&padapter->timer);
1733 if ( padapter->reconPhase == RECON_PHASE_LAST )
1734 {
1735 if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
1736 {
1737 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 1 : 0;
1738 DEB (printk ("\npci2220i: FAILURE 10"));
1739 if ( InitFailover (padapter, pdev) )
1740 OpDone (padapter, DecodeError (padapter, status));
1741 goto irq_return;
1742 }
1743 if ( WriteSignature (padapter, pdev, pdev->spigots[pdev->mirrorRecon], pdev->mirrorRecon) )
1744 {
1745 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
1746 DEB (printk ("\npci2220i: FAILURE 11"));
1747 if ( InitFailover (padapter, pdev) )
1748 OpDone (padapter, DecodeError (padapter, status));
1749 goto irq_return;
1750 }
1751 padapter->reconPhase = RECON_PHASE_END;
1752 goto irq_return;
1753 }
1754 OpDone (padapter, DID_OK << 16);
1755 goto irq_return;
1756
1757 case RECON_PHASE_READY:
1758 status = inb_p (padapter->regStatCmd); // read the device status
1759 if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
1760 {
1761 del_timer (&padapter->timer);
1762 OpDone (padapter, DecodeError (padapter, status));
1763 goto irq_return;
1764 }
1765 SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon]);
1766 if ( WaitDrq (padapter) )
1767 {
1768 del_timer (&padapter->timer);
1769 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
1770 DEB (printk ("\npci2220i: FAILURE 12"));
1771 if ( InitFailover (padapter, pdev) )
1772 OpDone (padapter, DecodeError (padapter, status));
1773 goto irq_return;
1774 }
1775 SelectSpigot (padapter, pdev->spigot | SEL_COPY | padapter->bigD);
1776 padapter->reconPhase = RECON_PHASE_COPY;
1777 padapter->expectingIRQ = TRUE;
1778 if ( padapter->timingPIO )
1779 {
1780 insw (padapter->regData, padapter->kBuffer, padapter->reconSize * (BYTES_PER_SECTOR / 2));
1781 }
1782 else
1783 {
1784 if ( (padapter->timingMode > 3) )
1785 {
1786 if ( padapter->bigD )
1787 outl (BIGD_DATA_MODE3, padapter->regDmaAddrLoc);
1788 else
1789 outl (DALE_DATA_MODE3, padapter->regDmaAddrLoc);
1790 }
1791 else
1792 outl (padapter->timingAddress, padapter->regDmaAddrLoc);
1793 outl (padapter->kBufferDma, padapter->regDmaAddrPci);
1794 outl (padapter->reconSize * BYTES_PER_SECTOR, padapter->regDmaCount);
1795 outb_p (8, padapter->regDmaDesc); // read operation
1796 if ( padapter->bigD )
1797 outb_p (8, padapter->regDmaMode); // no interrupt
1798 else
1799 outb_p (1, padapter->regDmaMode); // no interrupt
1800 outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear
1801 }
1802 goto irq_return;
1803
1804 case RECON_PHASE_COPY:
1805 pdev->DiskMirror[pdev->mirrorRecon].reconstructPoint += padapter->reconSize;
1806
1807 case RECON_PHASE_UPDATE:
1808 SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon] | SEL_IRQ_OFF);
1809 status = inb_p (padapter->regStatCmd); // read the device status
1810 del_timer (&padapter->timer);
1811 if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
1812 {
1813 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
1814 DEB (printk ("\npci2220i: FAILURE 13"));
1815 DEB (printk ("\n status register = %X error = %X", status, inb_p (padapter->regError)));
1816 if ( InitFailover (padapter, pdev) )
1817 OpDone (padapter, DecodeError (padapter, status));
1818 goto irq_return;
1819 }
1820 OpDone (padapter, DID_OK << 16);
1821 goto irq_return;
1822
1823 case RECON_PHASE_END:
1824 status = inb_p (padapter->regStatCmd); // read the device status
1825 del_timer (&padapter->timer);
1826 if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
1827 {
1828 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
1829 DEB (printk ("\npci2220i: FAILURE 14"));
1830 if ( InitFailover (padapter, pdev) )
1831 OpDone (padapter, DecodeError (padapter, status));
1832 goto irq_return;
1833 }
1834 pdev->reconOn = 0;
1835 if ( padapter->bigD )
1836 {
1837 for ( z = 0; z < padapter->numberOfDrives; z++ )
1838 {
1839 if ( padapter->device[z].DiskMirror[0].status & UCBF_SURVIVOR )
1840 {
1841 Alarm (padapter, padapter->device[z].deviceID[0] ^ 2);
1842 MuteAlarm (padapter);
1843 }
1844 if ( padapter->device[z].DiskMirror[1].status & UCBF_SURVIVOR )
1845 {
1846 Alarm (padapter, padapter->device[z].deviceID[1] ^ 2);
1847 MuteAlarm (padapter);
1848 }
1849 }
1850 }
1851 OpDone (padapter, DID_OK << 16);
1852 goto irq_return;
1853
1854 default:
1855 goto irq_return;
1856 }
1857 }
1858
1859 switch ( padapter->cmd ) // decide how to handle the interrupt
1860 {
1861 case READ_CMD:
1862 if ( padapter->sectorCount )
1863 {
1864 status = inb_p (padapter->regStatCmd); // read the device status
1865 if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
1866 {
1867 if ( pdev->raid )
1868 {
1869 padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 1 : 0;
1870 del_timer (&padapter->timer);
1871 DEB (printk ("\npci2220i: FAILURE 15"));
1872 if ( !InitFailover (padapter, pdev) )
1873 goto irq_return;
1874 }
1875 break;
1876 }
1877 if ( padapter->timingPIO )
1878 {
1879 insw (padapter->regData, padapter->kBuffer, padapter->readCount / 2);
1880 padapter->sectorCount -= padapter->readCount / BYTES_PER_SECTOR;
1881 WalkScatGath (padapter, TRUE, padapter->readCount);
1882 if ( !padapter->sectorCount )
1883 {
1884 status = 0;
1885 break;
1886 }
1887 }
1888 else
1889 {
1890 if ( padapter->readCount )
1891 WalkScatGath (padapter, TRUE, padapter->readCount);
1892 BusMaster (padapter, 1, 1);
1893 }
1894 padapter->expectingIRQ = TRUE;
1895 goto irq_return;
1896 }
1897 if ( padapter->readCount && !padapter->timingPIO )
1898 WalkScatGath (padapter, TRUE, padapter->readCount);
1899 status = 0;
1900 break;
1901
1902 case WRITE_CMD:
1903 if ( pdev->raid )
1904 {
1905 SelectSpigot (padapter, pdev->spigots[0] | SEL_IRQ_OFF);
1906 status = inb_p (padapter->regStatCmd); // read the device status
1907 SelectSpigot (padapter, pdev->spigots[1] | SEL_IRQ_OFF);
1908 status1 = inb_p (padapter->regStatCmd); // read the device status
1909 }
1910 else
1911 SelectSpigot (padapter, pdev->spigot | SEL_IRQ_OFF);
1912 status = inb_p (padapter->regStatCmd); // read the device status
1913 status1 = 0;
1914
1915 if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
1916 {
1917 if ( pdev->raid && !(status1 & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT)) )
1918 {
1919 padapter->survivor = 1;
1920 del_timer (&padapter->timer);
1921 SelectSpigot (padapter, pdev->spigot | SEL_IRQ_OFF);
1922 DEB (printk ("\npci2220i: FAILURE 16 status = %X error = %X", status, inb_p (padapter->regError)));
1923 if ( !InitFailover (padapter, pdev) )
1924 goto irq_return;
1925 }
1926 break;
1927 }
1928 if ( pdev->raid )
1929 {
1930 if ( status1 & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
1931 {
1932 padapter->survivor = 0;
1933 del_timer (&padapter->timer);
1934 DEB (printk ("\npci2220i: FAILURE 17 status = %X error = %X", status1, inb_p (padapter->regError)));
1935 if ( !InitFailover (padapter, pdev) )
1936 goto irq_return;
1937 status = status1;
1938 break;
1939 }
1940 if ( padapter->sectorCount )
1941 {
1942 status = WriteDataBoth (padapter, pdev);
1943 if ( status )
1944 {
1945 padapter->survivor = status >> 1;
1946 del_timer (&padapter->timer);
1947 DEB (printk ("\npci2220i: FAILURE 18"));
1948 if ( !InitFailover (padapter, pdev) )
1949 goto irq_return;
1950 SelectSpigot (padapter, pdev->spigots[status] | SEL_IRQ_OFF);
1951 status = inb_p (padapter->regStatCmd); // read the device status
1952 break;
1953 }
1954 padapter->expectingIRQ = TRUE;
1955 goto irq_return;
1956 }
1957 status = 0;
1958 break;
1959 }
1960 if ( padapter->sectorCount )
1961 {
1962 SelectSpigot (padapter, pdev->spigot | padapter->bigD);
1963 status = WriteData (padapter);
1964 if ( status )
1965 break;
1966 padapter->expectingIRQ = TRUE;
1967 goto irq_return;
1968 }
1969 status = 0;
1970 break;
1971
1972 case IDE_COMMAND_IDENTIFY:
1973 {
1974 PINQUIRYDATA pinquiryData = SCpnt->request_buffer;
1975 PIDENTIFY_DATA pid = (PIDENTIFY_DATA)padapter->kBuffer;
1976
1977 status = inb_p (padapter->regStatCmd);
1978 if ( status & IDE_STATUS_DRQ )
1979 {
1980 insw (padapter->regData, pid, sizeof (IDENTIFY_DATA) >> 1);
1981
1982 memset (pinquiryData, 0, SCpnt->request_bufflen); // Zero INQUIRY data structure.
1983 pinquiryData->DeviceType = 0;
1984 pinquiryData->Versions = 2;
1985 pinquiryData->AdditionalLength = 35 - 4;
1986
1987 // Fill in vendor identification fields.
1988 for ( z = 0; z < 20; z += 2 )
1989 {
1990 pinquiryData->VendorId[z] = ((UCHAR *)pid->ModelNumber)[z + 1];
1991 pinquiryData->VendorId[z + 1] = ((UCHAR *)pid->ModelNumber)[z];
1992 }
1993
1994 // Initialize unused portion of product id.
1995 for ( z = 0; z < 4; z++ )
1996 pinquiryData->ProductId[12 + z] = ' ';
1997
1998 // Move firmware revision from IDENTIFY data to
1999 // product revision in INQUIRY data.
2000 for ( z = 0; z < 4; z += 2 )
2001 {
2002 pinquiryData->ProductRevisionLevel[z] = ((UCHAR *)pid->FirmwareRevision)[z + 1];
2003 pinquiryData->ProductRevisionLevel[z + 1] = ((UCHAR *)pid->FirmwareRevision)[z];
2004 }
2005 if ( pdev == padapter->device )
2006 *((USHORT *)(&pinquiryData->VendorSpecific)) = DEVICE_DALE_1;
2007
2008 status = 0;
2009 }
2010 break;
2011 }
2012
2013 default:
2014 status = 0;
2015 break;
2016 }
2017
2018 del_timer (&padapter->timer);
2019 if ( status )
2020 {
2021 DEB (printk ("\npci2220i Interrupt handler return error"));
2022 zl = DecodeError (padapter, status);
2023 }
2024 else
2025 zl = DID_OK << 16;
2026
2027 OpDone (padapter, zl);
2028irq_return:
2029 spin_unlock_irqrestore(shost->host_lock, flags);
2030out:
2031 return IRQ_RETVAL(handled);
2032}
2033
2034/****************************************************************
2035 * Name: Pci2220i_QueueCommand
2036 *
2037 * Description: Process a queued command from the SCSI manager.
2038 *
2039 * Parameters: SCpnt - Pointer to SCSI command structure.
2040 * done - Pointer to done function to call.
2041 *
2042 * Returns: Status code.
2043 *
2044 ****************************************************************/
2045int Pci2220i_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
2046 {
2047 UCHAR *cdb = (UCHAR *)SCpnt->cmnd; // Pointer to SCSI CDB
2048 PADAPTER2220I padapter = HOSTDATA(SCpnt->device->host); // Pointer to adapter control structure
2049 POUR_DEVICE pdev = &padapter->device[SCpnt->device->id];// Pointer to device information
2050 UCHAR rc; // command return code
2051 int z;
2052 PDEVICE_RAID1 pdr;
2053
2054 SCpnt->scsi_done = done;
2055 padapter->SCpnt = SCpnt; // Save this command data
2056 padapter->readCount = 0;
2057
2058 if ( SCpnt->use_sg )
2059 {
2060 padapter->currentSgBuffer = ((struct scatterlist *)SCpnt->request_buffer)[0].address;
2061 padapter->currentSgCount = ((struct scatterlist *)SCpnt->request_buffer)[0].length;
2062 }
2063 else
2064 {
2065 padapter->currentSgBuffer = SCpnt->request_buffer;
2066 padapter->currentSgCount = SCpnt->request_bufflen;
2067 }
2068 padapter->nextSg = 1;
2069
2070 if ( !done )
2071 {
2072 printk("pci2220i_queuecommand: %02X: done can't be NULL\n", *cdb);
2073 return 0;
2074 }
2075
2076 if ( padapter->atapi )
2077 {
2078 UCHAR zlo, zhi;
2079
2080 DEB (printk ("\nPCI2242I: ID %d, LUN %d opcode %X ", SCpnt->device->id, SCpnt->device->lun, *cdb));
2081 padapter->pdev = pdev;
2082 if ( !pdev->byte6 || SCpnt->device->lun )
2083 {
2084 OpDone (padapter, DID_BAD_TARGET << 16);
2085 return 0;
2086 }
2087
2088 padapter->atapiSpecial = FALSE;
2089 padapter->reqSense = FALSE;
2090 memset (padapter->atapiCdb, 0, 16);
2091 SelectSpigot (padapter, pdev->spigot); // select the spigot
2092 AtapiDevice (padapter, pdev->byte6); // select the drive
2093 if ( AtapiWaitReady (padapter, 100) )
2094 {
2095 OpDone (padapter, DID_NO_CONNECT << 16);
2096 return 0;
2097 }
2098
2099 switch ( cdb[0] )
2100 {
2101 case SCSIOP_MODE_SENSE:
2102 case SCSIOP_MODE_SELECT:
2103 Scsi2Atapi (padapter, SCpnt);
2104 z = SCpnt->request_bufflen + 4;
2105 break;
2106 case SCSIOP_READ6:
2107 case SCSIOP_WRITE6:
2108 Scsi2Atapi (padapter, SCpnt);
2109 z = SCpnt->request_bufflen;
2110 break;
2111 default:
2112 memcpy (padapter->atapiCdb, cdb, SCpnt->cmd_len);
2113 z = SCpnt->request_bufflen;
2114 break;
2115 }
2116 if ( z > ATAPI_TRANSFER )
2117 z = ATAPI_TRANSFER;
2118 zlo = (UCHAR)(z & 0xFF);
2119 zhi = (UCHAR)(z >> 8);
2120
2121 AtapiCountLo (padapter, zlo);
2122 AtapiCountHi (padapter, zhi);
2123 outb_p (0, padapter->regError);
2124 WriteCommand (padapter, IDE_COMMAND_ATAPI_PACKET);
2125 if ( pdev->cmdDrqInt )
2126 return 0;
2127
2128 if ( AtapiWaitDrq (padapter, 500) )
2129 {
2130 OpDone (padapter, DID_ERROR << 16);
2131 return 0;
2132 }
2133 AtapiSendCdb (padapter, pdev, padapter->atapiCdb);
2134 return 0;
2135 }
2136
2137 if ( padapter->reconPhase )
2138 return 0;
2139 if ( padapter->reconTimer.data )
2140 {
2141 del_timer (&padapter->reconTimer);
2142 padapter->reconTimer.data = 0;
2143 }
2144
2145 if ( (SCpnt->device->id >= padapter->numberOfDrives) || SCpnt->device->lun )
2146 {
2147 OpDone (padapter, DID_BAD_TARGET << 16);
2148 return 0;
2149 }
2150
2151 switch ( *cdb )
2152 {
2153 case SCSIOP_INQUIRY: // inquiry CDB
2154 {
2155 if ( cdb[2] == SC_MY_RAID )
2156 {
2157 switch ( cdb[3] )
2158 {
2159 case MY_SCSI_REBUILD:
2160 for ( z = 0; z < padapter->numberOfDrives; z++ )
2161 {
2162 pdev = &padapter->device[z];
2163 if ( ((pdev->DiskMirror[0].status & UCBF_SURVIVOR) && (pdev->DiskMirror[1].status & UCBF_MIRRORED)) ||
2164 ((pdev->DiskMirror[1].status & UCBF_SURVIVOR) && (pdev->DiskMirror[0].status & UCBF_MIRRORED)) )
2165 {
2166 padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
2167 }
2168 }
2169 OpDone (padapter, DID_OK << 16);
2170 break;
2171 case MY_SCSI_ALARMMUTE:
2172 MuteAlarm (padapter);
2173 OpDone (padapter, DID_OK << 16);
2174 break;
2175 case MY_SCSI_DEMOFAIL:
2176 padapter->demoFail = TRUE;
2177 OpDone (padapter, DID_OK << 16);
2178 break;
2179 default:
2180 z = cdb[5]; // get index
2181 pdr = (PDEVICE_RAID1)SCpnt->request_buffer;
2182 if ( padapter->raidData[z] )
2183 {
2184 memcpy (&pdr->DiskRaid1, padapter->raidData[z], sizeof (DISK_MIRROR));
2185 if ( padapter->raidData[z]->reconstructPoint > padapter->raidData[z ^ 2]->reconstructPoint )
2186 pdr->TotalSectors = padapter->raidData[z]->reconstructPoint;
2187 else
2188 pdr->TotalSectors = padapter->raidData[z ^ 2]->reconstructPoint;
2189 }
2190 else
2191 memset (pdr, 0, sizeof (DEVICE_RAID1));
2192 OpDone (padapter, DID_OK << 16);
2193 break;
2194 }
2195 return 0;
2196 }
2197 padapter->cmd = IDE_COMMAND_IDENTIFY;
2198 break;
2199 }
2200
2201 case SCSIOP_TEST_UNIT_READY: // test unit ready CDB
2202 OpDone (padapter, DID_OK << 16);
2203 return 0;
2204 case SCSIOP_READ_CAPACITY: // read capctiy CDB
2205 {
2206 PREAD_CAPACITY_DATA pdata = (PREAD_CAPACITY_DATA)SCpnt->request_buffer;
2207
2208 pdata->blksiz = 0x20000;
2209 XANY2SCSI ((UCHAR *)&pdata->blks, pdev->blocks);
2210 OpDone (padapter, DID_OK << 16);
2211 return 0;
2212 }
2213 case SCSIOP_VERIFY: // verify CDB
2214 padapter->startSector = XSCSI2LONG (&cdb[2]);
2215 padapter->sectorCount = (UCHAR)((USHORT)cdb[8] | ((USHORT)cdb[7] << 8));
2216 padapter->cmd = IDE_COMMAND_VERIFY;
2217 break;
2218 case SCSIOP_READ: // read10 CDB
2219 padapter->startSector = XSCSI2LONG (&cdb[2]);
2220 padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8);
2221 padapter->cmd = READ_CMD;
2222 break;
2223 case SCSIOP_READ6: // read6 CDB
2224 padapter->startSector = SCSI2LONG (&cdb[1]);
2225 padapter->sectorCount = cdb[4];
2226 padapter->cmd = READ_CMD;
2227 break;
2228 case SCSIOP_WRITE: // write10 CDB
2229 padapter->startSector = XSCSI2LONG (&cdb[2]);
2230 padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8);
2231 padapter->cmd = WRITE_CMD;
2232 break;
2233 case SCSIOP_WRITE6: // write6 CDB
2234 padapter->startSector = SCSI2LONG (&cdb[1]);
2235 padapter->sectorCount = cdb[4];
2236 padapter->cmd = WRITE_CMD;
2237 break;
2238 default:
2239 DEB (printk ("pci2220i_queuecommand: Unsupported command %02X\n", *cdb));
2240 OpDone (padapter, DID_ERROR << 16);
2241 return 0;
2242 }
2243
2244 if ( padapter->reconPhase )
2245 return 0;
2246
2247 padapter->pdev = pdev;
2248
2249 while ( padapter->demoFail )
2250 {
2251 pdev = padapter->pdev = &padapter->device[0];
2252 padapter->demoFail = FALSE;
2253 if ( !pdev->raid ||
2254 (pdev->DiskMirror[0].status & UCBF_SURVIVOR) ||
2255 (pdev->DiskMirror[1].status & UCBF_SURVIVOR) )
2256 {
2257 break;
2258 }
2259 if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
2260 padapter->survivor = 1;
2261 else
2262 padapter->survivor = 0;
2263 DEB (printk ("\npci2220i: FAILURE 19"));
2264 if ( InitFailover (padapter, pdev) )
2265 break;
2266 return 0;
2267 }
2268
2269 StartTimer (padapter);
2270 if ( pdev->raid && (padapter->cmd == WRITE_CMD) )
2271 {
2272 rc = IdeCmdBoth (padapter, pdev);
2273 if ( !rc )
2274 rc = WriteDataBoth (padapter, pdev);
2275 if ( rc )
2276 {
2277 del_timer (&padapter->timer);
2278 padapter->expectingIRQ = 0;
2279 padapter->survivor = rc >> 1;
2280 DEB (printk ("\npci2220i: FAILURE 20"));
2281 if ( InitFailover (padapter, pdev) )
2282 {
2283 OpDone (padapter, DID_ERROR << 16);
2284 return 0;
2285 }
2286 }
2287 }
2288 else
2289 {
2290 rc = IdeCmd (padapter, pdev);
2291 if ( (padapter->cmd == WRITE_CMD) && !rc )
2292 rc = WriteData (padapter);
2293 if ( rc )
2294 {
2295 del_timer (&padapter->timer);
2296 padapter->expectingIRQ = 0;
2297 if ( pdev->raid )
2298 {
2299 padapter->survivor = (pdev->spigot ^ 3) >> 1;
2300 DEB (printk ("\npci2220i: FAILURE 21"));
2301 if ( !InitFailover (padapter, pdev) )
2302 return 0;
2303 }
2304 OpDone (padapter, DID_ERROR << 16);
2305 return 0;
2306 }
2307 }
2308 return 0;
2309 }
2310/****************************************************************
2311 * Name: ReadFlash
2312 *
2313 * Description: Read information from controller Flash memory.
2314 *
2315 * Parameters: padapter - Pointer to host interface data structure.
2316 * pdata - Pointer to data structures.
2317 * base - base address in Flash.
2318 * length - lenght of data space in bytes.
2319 *
2320 * Returns: Nothing.
2321 *
2322 ****************************************************************/
2323static VOID ReadFlash (PADAPTER2220I padapter, VOID *pdata, ULONG base, ULONG length)
2324 {
2325 ULONG oldremap;
2326 UCHAR olddesc;
2327 ULONG z;
2328 UCHAR *pd = (UCHAR *)pdata;
2329
2330 oldremap = inl (padapter->regRemap); // save values to restore later
2331 olddesc = inb_p (padapter->regDesc);
2332
2333 outl (base | 1, padapter->regRemap); // remap to Flash space as specified
2334 outb_p (0x40, padapter->regDesc); // describe remap region as 8 bit
2335 for ( z = 0; z < length; z++) // get "length" data count
2336 *pd++ = inb_p (padapter->regBase + z); // read in the data
2337
2338 outl (oldremap, padapter->regRemap); // restore remap register values
2339 outb_p (olddesc, padapter->regDesc);
2340 }
2341/****************************************************************
2342 * Name: GetRegs
2343 *
2344 * Description: Initialize the regester information.
2345 *
2346 * Parameters: pshost - Pointer to SCSI host data structure.
2347 * bigd - PCI-2240I identifier
2348 * pcidev - Pointer to device data structure.
2349 *
2350 * Returns: TRUE if failure to install.
2351 *
2352 ****************************************************************/
2353static USHORT GetRegs (struct Scsi_Host *pshost, BOOL bigd, struct pci_dev *pcidev)
2354 {
2355 PADAPTER2220I padapter;
2356 int setirq;
2357 int z;
2358 USHORT zr, zl;
2359 UCHAR *consistent;
2360 dma_addr_t consistentDma;
2361
2362 padapter = HOSTDATA(pshost);
2363 memset (padapter, 0, sizeof (ADAPTER2220I));
2364 memset (&DaleSetup, 0, sizeof (DaleSetup));
2365 memset (DiskMirror, 0, sizeof (DiskMirror));
2366
2367 zr = pci_resource_start (pcidev, 1);
2368 zl = pci_resource_start (pcidev, 2);
2369
2370 padapter->basePort = zr;
2371 padapter->regRemap = zr + RTR_LOCAL_REMAP; // 32 bit local space remap
2372 padapter->regDesc = zr + RTR_REGIONS; // 32 bit local region descriptor
2373 padapter->regRange = zr + RTR_LOCAL_RANGE; // 32 bit local range
2374 padapter->regIrqControl = zr + RTR_INT_CONTROL_STATUS; // 16 bit interrupt control and status
2375 padapter->regScratchPad = zr + RTR_MAILBOX; // 16 byte scratchpad I/O base address
2376
2377 padapter->regBase = zl;
2378 padapter->regData = zl + REG_DATA; // data register I/O address
2379 padapter->regError = zl + REG_ERROR; // error register I/O address
2380 padapter->regSectCount = zl + REG_SECTOR_COUNT; // sector count register I/O address
2381 padapter->regLba0 = zl + REG_LBA_0; // least significant byte of LBA
2382 padapter->regLba8 = zl + REG_LBA_8; // next least significant byte of LBA
2383 padapter->regLba16 = zl + REG_LBA_16; // next most significan byte of LBA
2384 padapter->regLba24 = zl + REG_LBA_24; // head and most 4 significant bits of LBA
2385 padapter->regStatCmd = zl + REG_STAT_CMD; // status on read and command on write register
2386 padapter->regStatSel = zl + REG_STAT_SEL; // board status on read and spigot select on write register
2387 padapter->regFail = zl + REG_FAIL;
2388 padapter->regAltStat = zl + REG_ALT_STAT;
2389 padapter->pcidev = pcidev;
2390
2391 if ( bigd )
2392 {
2393 padapter->regDmaDesc = zr + RTR_DMA0_DESC_PTR; // address of the DMA discriptor register for direction of transfer
2394 padapter->regDmaCmdStat = zr + RTR_DMA_COMMAND_STATUS; // Byte #0 of DMA command status register
2395 padapter->regDmaAddrPci = zr + RTR_DMA0_PCI_ADDR; // 32 bit register for PCI address of DMA
2396 padapter->regDmaAddrLoc = zr + RTR_DMA0_LOCAL_ADDR; // 32 bit register for local bus address of DMA
2397 padapter->regDmaCount = zr + RTR_DMA0_COUNT; // 32 bit register for DMA transfer count
2398 padapter->regDmaMode = zr + RTR_DMA0_MODE + 1; // 32 bit register for DMA mode control
2399 padapter->bigD = SEL_NEW_SPEED_1; // set spigot speed control bit
2400 }
2401 else
2402 {
2403 padapter->regDmaDesc = zl + RTL_DMA1_DESC_PTR; // address of the DMA discriptor register for direction of transfer
2404 padapter->regDmaCmdStat = zl + RTL_DMA_COMMAND_STATUS + 1; // Byte #1 of DMA command status register
2405 padapter->regDmaAddrPci = zl + RTL_DMA1_PCI_ADDR; // 32 bit register for PCI address of DMA
2406 padapter->regDmaAddrLoc = zl + RTL_DMA1_LOCAL_ADDR; // 32 bit register for local bus address of DMA
2407 padapter->regDmaCount = zl + RTL_DMA1_COUNT; // 32 bit register for DMA transfer count
2408 padapter->regDmaMode = zl + RTL_DMA1_MODE + 1; // 32 bit register for DMA mode control
2409 }
2410
2411 padapter->numberOfDrives = inb_p (padapter->regScratchPad + BIGD_NUM_DRIVES);
2412 if ( !bigd && !padapter->numberOfDrives ) // if no devices on this board
2413 return TRUE;
2414
2415 pshost->irq = pcidev->irq;
2416 setirq = 1;
2417 for ( z = 0; z < Installed; z++ ) // scan for shared interrupts
2418 {
2419 if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses
2420 setirq = 0;
2421 }
2422 if ( setirq ) // if not shared, posses
2423 {
2424 if ( request_irq (pshost->irq, Irq_Handler, SA_SHIRQ, "pci2220i", padapter) < 0 )
2425 {
2426 if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2220i", padapter) < 0 )
2427 {
2428 printk ("Unable to allocate IRQ for PCI-2220I controller.\n");
2429 return TRUE;
2430 }
2431 }
2432 padapter->irqOwned = pshost->irq; // set IRQ as owned
2433 }
2434
2435 if ( padapter->numberOfDrives )
2436 consistent = pci_alloc_consistent (pcidev, SECTORSXFER * BYTES_PER_SECTOR, &consistentDma);
2437 else
2438 consistent = pci_alloc_consistent (pcidev, ATAPI_TRANSFER, &consistentDma);
2439 if ( !consistent )
2440 {
2441 printk ("Unable to allocate DMA buffer for PCI-2220I controller.\n");
2442 free_irq (pshost->irq, padapter);
2443 return TRUE;
2444 }
2445 padapter->kBuffer = consistent;
2446 padapter->kBufferDma = consistentDma;
2447
2448 PsiHost[Installed] = pshost; // save SCSI_HOST pointer
2449 pshost->io_port = padapter->basePort;
2450 pshost->n_io_port = 0xFF;
2451 pshost->unique_id = padapter->regBase;
2452
2453 outb_p (0x01, padapter->regRange); // fix our range register because other drivers want to tromp on it
2454
2455 padapter->timingMode = inb_p (padapter->regScratchPad + DALE_TIMING_MODE);
2456 if ( padapter->timingMode >= 2 )
2457 {
2458 if ( bigd )
2459 padapter->timingAddress = ModeArray2[padapter->timingMode - 2];
2460 else
2461 padapter->timingAddress = ModeArray[padapter->timingMode - 2];
2462 }
2463 else
2464 padapter->timingPIO = TRUE;
2465
2466 ReadFlash (padapter, &DaleSetup, DALE_FLASH_SETUP, sizeof (SETUP));
2467 ReadFlash (padapter, &DiskMirror, DALE_FLASH_RAID, sizeof (DiskMirror));
2468
2469 return FALSE;
2470 }
2471/****************************************************************
2472 * Name: SetupFinish
2473 *
2474 * Description: Complete the driver initialization process for a card
2475 *
2476 * Parameters: padapter - Pointer to SCSI host data structure.
2477 * str - Pointer to board type string.
2478 *
2479 * Returns: Nothing.
2480 *
2481 ****************************************************************/
2482VOID SetupFinish (PADAPTER2220I padapter, char *str, int irq)
2483 {
2484 init_timer (&padapter->timer);
2485 padapter->timer.function = TimerExpiry;
2486 padapter->timer.data = (unsigned long)padapter;
2487 init_timer (&padapter->reconTimer);
2488 padapter->reconTimer.function = ReconTimerExpiry;
2489 padapter->reconTimer.data = (unsigned long)padapter;
2490 printk("\nPCI-%sI EIDE CONTROLLER: at I/O = %lX/%lX IRQ = %d\n", str, padapter->basePort, padapter->regBase, irq);
2491 printk("Version %s, Compiled %s %s\n\n", PCI2220I_VERSION, __DATE__, __TIME__);
2492 }
2493/****************************************************************
2494 * Name: Pci2220i_Detect
2495 *
2496 * Description: Detect and initialize our boards.
2497 *
2498 * Parameters: tpnt - Pointer to SCSI host template structure.
2499 *
2500 * Returns: Number of adapters installed.
2501 *
2502 ****************************************************************/
2503int Pci2220i_Detect (Scsi_Host_Template *tpnt)
2504 {
2505 struct Scsi_Host *pshost;
2506 PADAPTER2220I padapter;
2507 POUR_DEVICE pdev;
2508 int unit;
2509 int z;
2510 USHORT raidon;
2511 UCHAR spigot1, spigot2;
2512 UCHAR device;
2513 struct pci_dev *pcidev = NULL;
2514
2515 while ( (pcidev = pci_find_device (VENDOR_PSI, DEVICE_DALE_1, pcidev)) != NULL )
2516 {
2517 if (pci_enable_device(pcidev))
2518 continue;
2519 pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
2520 if(pshost==NULL)
2521 continue;
2522
2523 padapter = HOSTDATA(pshost);
2524
2525 if ( GetRegs (pshost, FALSE, pcidev) )
2526 goto unregister;
2527
2528 scsi_set_device(pshost, &pcidev->dev);
2529 pshost->max_id = padapter->numberOfDrives;
2530 for ( z = 0; z < padapter->numberOfDrives; z++ )
2531 {
2532 unit = inb_p (padapter->regScratchPad + DALE_CHANNEL_DEVICE_0 + z) & 0x0F;
2533 pdev = &padapter->device[z];
2534 pdev->byte6 = (UCHAR)(((unit & 1) << 4) | 0xE0);
2535 pdev->spigot = (UCHAR)(1 << (unit >> 1));
2536 pdev->sectors = DaleSetup.setupDevice[unit].sectors;
2537 pdev->heads = DaleSetup.setupDevice[unit].heads;
2538 pdev->cylinders = DaleSetup.setupDevice[unit].cylinders;
2539 pdev->blocks = DaleSetup.setupDevice[unit].blocks;
2540
2541 if ( !z )
2542 {
2543 DiskMirror[0].status = inb_p (padapter->regScratchPad + DALE_RAID_0_STATUS);
2544 DiskMirror[1].status = inb_p (padapter->regScratchPad + DALE_RAID_1_STATUS);
2545 if ( (DiskMirror[0].signature == SIGNATURE) && (DiskMirror[1].signature == SIGNATURE) &&
2546 (DiskMirror[0].pairIdentifier == (DiskMirror[1].pairIdentifier ^ 1)) )
2547 {
2548 raidon = TRUE;
2549 if ( unit > (unit ^ 2) )
2550 unit = unit ^ 2;
2551 }
2552 else
2553 raidon = FALSE;
2554
2555 memcpy (pdev->DiskMirror, DiskMirror, sizeof (DiskMirror));
2556 padapter->raidData[0] = &pdev->DiskMirror[0];
2557 padapter->raidData[2] = &pdev->DiskMirror[1];
2558
2559 spigot1 = spigot2 = FALSE;
2560 pdev->spigots[0] = 1;
2561 pdev->spigots[1] = 2;
2562 pdev->lastsectorlba[0] = InlineIdentify (padapter, 1, 0);
2563 pdev->lastsectorlba[1] = InlineIdentify (padapter, 2, 0);
2564
2565 if ( !(pdev->DiskMirror[1].status & UCBF_SURVIVOR) && pdev->lastsectorlba[0] )
2566 spigot1 = TRUE;
2567 if ( !(pdev->DiskMirror[0].status & UCBF_SURVIVOR) && pdev->lastsectorlba[1] )
2568 spigot2 = TRUE;
2569 if ( pdev->DiskMirror[0].status & DiskMirror[1].status & UCBF_SURVIVOR )
2570 spigot1 = TRUE;
2571
2572 if ( spigot1 && (pdev->DiskMirror[0].status & UCBF_REBUILD) )
2573 InlineReadSignature (padapter, pdev, 0);
2574 if ( spigot2 && (pdev->DiskMirror[1].status & UCBF_REBUILD) )
2575 InlineReadSignature (padapter, pdev, 1);
2576
2577 if ( spigot1 && spigot2 && raidon )
2578 {
2579 pdev->raid = 1;
2580 if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
2581 pdev->spigot = 2;
2582 else
2583 pdev->spigot = 1;
2584 if ( (pdev->DiskMirror[0].status & UCBF_REBUILD) || (pdev->DiskMirror[1].status & UCBF_REBUILD) )
2585 padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
2586 }
2587 else
2588 {
2589 if ( spigot1 )
2590 {
2591 if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
2592 goto unregister;
2593 pdev->DiskMirror[0].status = UCBF_MIRRORED | UCBF_SURVIVOR;
2594 pdev->spigot = 1;
2595 }
2596 else
2597 {
2598 if ( pdev->DiskMirror[1].status & UCBF_REBUILD )
2599 goto unregister;
2600 pdev->DiskMirror[1].status = UCBF_MIRRORED | UCBF_SURVIVOR;
2601 pdev->spigot = 2;
2602 }
2603 if ( DaleSetup.rebootRebuild && raidon )
2604 padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
2605 }
2606
2607 if ( raidon )
2608 break;
2609 }
2610 }
2611
2612 SetupFinish (padapter, "2220", pshost->irq);
2613
2614 if ( ++Installed < MAXADAPTER )
2615 continue;
2616 break;
2617unregister:;
2618 scsi_unregister (pshost);
2619 }
2620
2621 while ( (pcidev = pci_find_device (VENDOR_PSI, DEVICE_BIGD_1, pcidev)) != NULL )
2622 {
2623 pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
2624 padapter = HOSTDATA(pshost);
2625
2626 if ( GetRegs (pshost, TRUE, pcidev) )
2627 goto unregister1;
2628
2629 for ( z = 0; z < BIGD_MAXDRIVES; z++ )
2630 DiskMirror[z].status = inb_p (padapter->regScratchPad + BIGD_RAID_0_STATUS + z);
2631
2632 scsi_set_pci_device(pshost, pcidev);
2633 pshost->max_id = padapter->numberOfDrives;
2634 padapter->failRegister = inb_p (padapter->regScratchPad + BIGD_ALARM_IMAGE);
2635 for ( z = 0; z < padapter->numberOfDrives; z++ )
2636 {
2637 unit = inb_p (padapter->regScratchPad + BIGD_DEVICE_0 + z);
2638 pdev = &padapter->device[z];
2639 pdev->byte6 = (UCHAR)(((unit & 1) << 4) | 0xE0);
2640 pdev->spigot = (UCHAR)(1 << (unit >> 1));
2641 pdev->sectors = DaleSetup.setupDevice[unit].sectors;
2642 pdev->heads = DaleSetup.setupDevice[unit].heads;
2643 pdev->cylinders = DaleSetup.setupDevice[unit].cylinders;
2644 pdev->blocks = DaleSetup.setupDevice[unit].blocks;
2645
2646 if ( (DiskMirror[unit].signature == SIGNATURE) && (DiskMirror[unit ^ 2].signature == SIGNATURE) &&
2647 (DiskMirror[unit].pairIdentifier == (DiskMirror[unit ^ 2].pairIdentifier ^ 1)) )
2648 {
2649 raidon = TRUE;
2650 if ( unit > (unit ^ 2) )
2651 unit = unit ^ 2;
2652 }
2653 else
2654 raidon = FALSE;
2655
2656 spigot1 = spigot2 = FALSE;
2657 memcpy (&pdev->DiskMirror[0], &DiskMirror[unit], sizeof (DISK_MIRROR));
2658 memcpy (&pdev->DiskMirror[1], &DiskMirror[unit ^ 2], sizeof (DISK_MIRROR));
2659 padapter->raidData[unit] = &pdev->DiskMirror[0];
2660 padapter->raidData[unit ^ 2] = &pdev->DiskMirror[1];
2661 pdev->spigots[0] = 1 << (unit >> 1);
2662 pdev->spigots[1] = 1 << ((unit ^ 2) >> 1);
2663 pdev->deviceID[0] = unit;
2664 pdev->deviceID[1] = unit ^ 2;
2665 pdev->lastsectorlba[0] = InlineIdentify (padapter, pdev->spigots[0], unit & 1);
2666 pdev->lastsectorlba[1] = InlineIdentify (padapter, pdev->spigots[1], unit & 1);
2667
2668 if ( !(pdev->DiskMirror[1].status & UCBF_SURVIVOR) && pdev->lastsectorlba[0] )
2669 spigot1 = TRUE;
2670 if ( !(pdev->DiskMirror[0].status & UCBF_SURVIVOR) && pdev->lastsectorlba[1] )
2671 spigot2 = TRUE;
2672 if ( pdev->DiskMirror[0].status & pdev->DiskMirror[1].status & UCBF_SURVIVOR )
2673 spigot1 = TRUE;
2674
2675 if ( spigot1 && (pdev->DiskMirror[0].status & UCBF_REBUILD) )
2676 InlineReadSignature (padapter, pdev, 0);
2677 if ( spigot2 && (pdev->DiskMirror[1].status & UCBF_REBUILD) )
2678 InlineReadSignature (padapter, pdev, 1);
2679
2680 if ( spigot1 && spigot2 && raidon )
2681 {
2682 pdev->raid = 1;
2683 if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
2684 pdev->spigot = pdev->spigots[1];
2685 else
2686 pdev->spigot = pdev->spigots[0];
2687 if ( (pdev->DiskMirror[0].status & UCBF_REBUILD) || (pdev->DiskMirror[1].status & UCBF_REBUILD) )
2688 padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
2689 }
2690 else
2691 {
2692 if ( spigot1 )
2693 {
2694 if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
2695 goto unregister1;
2696 pdev->DiskMirror[0].status = UCBF_MIRRORED | UCBF_SURVIVOR;
2697 pdev->spigot = pdev->spigots[0];
2698 }
2699 else
2700 {
2701 if ( pdev->DiskMirror[1].status & UCBF_REBUILD )
2702 goto unregister;
2703 pdev->DiskMirror[1].status = UCBF_MIRRORED | UCBF_SURVIVOR;
2704 pdev->spigot = pdev->spigots[1];
2705 }
2706 if ( DaleSetup.rebootRebuild && raidon )
2707 padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
2708 }
2709 }
2710
2711 if ( !padapter->numberOfDrives ) // If no ATA devices then scan ATAPI
2712 {
2713 unit = 0;
2714 for ( spigot1 = 0; spigot1 < 4; spigot1++ )
2715 {
2716 for ( device = 0; device < 2; device++ )
2717 {
2718 DEB (printk ("\nPCI2242I: scanning for ID %d ", (spigot1 * 2) + device));
2719 pdev = &(padapter->device[(spigot1 * 2) + device]);
2720 pdev->byte6 = 0x0A | (device << 4);
2721 pdev->spigot = 1 << spigot1;
2722 if ( !AtapiReset (padapter, pdev) )
2723 {
2724 DEB (printk (" Device found "));
2725 if ( !AtapiIdentify (padapter, pdev) )
2726 {
2727 DEB (printk (" Device verified"));
2728 unit++;
2729 continue;
2730 }
2731 }
2732 pdev->spigot = pdev->byte6 = 0;
2733 }
2734 }
2735
2736 if ( unit )
2737 {
2738 padapter->atapi = TRUE;
2739 padapter->timingAddress = DALE_DATA_MODE3;
2740 outw_p (0x0900, padapter->regIrqControl); // Turn our interrupts on
2741 outw_p (0x0C41, padapter->regDmaMode - 1); // setup for 16 bits, ready enabled, done IRQ enabled, no incriment
2742 outb_p (0xFF, padapter->regFail); // all fail lights and alarm off
2743 pshost->max_id = 8;
2744 }
2745 }
2746 SetupFinish (padapter, "2240", pshost->irq);
2747
2748 if ( ++Installed < MAXADAPTER )
2749 continue;
2750 break;
2751unregister1:;
2752 scsi_unregister (pshost);
2753 }
2754
2755 NumAdapters = Installed;
2756 return Installed;
2757 }
2758/****************************************************************
2759 * Name: Pci2220i_Abort
2760 *
2761 * Description: Process the Abort command from the SCSI manager.
2762 *
2763 * Parameters: SCpnt - Pointer to SCSI command structure.
2764 *
2765 * Returns: Allways snooze.
2766 *
2767 ****************************************************************/
2768int Pci2220i_Abort (Scsi_Cmnd *SCpnt)
2769 {
2770 PADAPTER2220I padapter = HOSTDATA(SCpnt->device->host); // Pointer to adapter control structure
2771 POUR_DEVICE pdev = &padapter->device[SCpnt->device->id];// Pointer to device information
2772
2773 if ( !padapter->SCpnt )
2774 return SCSI_ABORT_NOT_RUNNING;
2775
2776 if ( padapter->atapi )
2777 {
2778 if ( AtapiReset (padapter, pdev) )
2779 return SCSI_ABORT_ERROR;
2780 OpDone (padapter, DID_ABORT << 16);
2781 return SCSI_ABORT_SUCCESS;
2782 }
2783 return SCSI_ABORT_SNOOZE;
2784 }
2785/****************************************************************
2786 * Name: Pci2220i_Reset
2787 *
2788 * Description: Process the Reset command from the SCSI manager.
2789 *
2790 * Parameters: SCpnt - Pointer to SCSI command structure.
2791 * flags - Flags about the reset command
2792 *
2793 * Returns: No active command at this time, so this means
2794 * that each time we got some kind of response the
2795 * last time through. Tell the mid-level code to
2796 * request sense information in order to decide what
2797 * to do next.
2798 *
2799 ****************************************************************/
2800int Pci2220i_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
2801 {
2802 PADAPTER2220I padapter = HOSTDATA(SCpnt->device->host); // Pointer to adapter control structure
2803 POUR_DEVICE pdev = &padapter->device[SCpnt->device->id];// Pointer to device information
2804
2805 if ( padapter->atapi )
2806 {
2807 if ( AtapiReset (padapter, pdev) )
2808 return SCSI_RESET_ERROR;
2809 return SCSI_RESET_SUCCESS;
2810 }
2811 return SCSI_RESET_PUNT;
2812 }
2813/****************************************************************
2814 * Name: Pci2220i_Release
2815 *
2816 * Description: Release resources allocated for a single each adapter.
2817 *
2818 * Parameters: pshost - Pointer to SCSI command structure.
2819 *
2820 * Returns: zero.
2821 *
2822 ****************************************************************/
2823int Pci2220i_Release (struct Scsi_Host *pshost)
2824 {
2825 PADAPTER2220I padapter = HOSTDATA (pshost);
2826 USHORT z;
2827
2828 if ( padapter->reconOn )
2829 {
2830 padapter->reconOn = FALSE; // shut down the hot reconstruct
2831 if ( padapter->reconPhase )
2832 mdelay (300);
2833 if ( padapter->reconTimer.data ) // is the timer running?
2834 {
2835 del_timer (&padapter->reconTimer);
2836 padapter->reconTimer.data = 0;
2837 }
2838 }
2839
2840 // save RAID status on the board
2841 if ( padapter->bigD )
2842 {
2843 outb_p (padapter->failRegister, padapter->regScratchPad + BIGD_ALARM_IMAGE);
2844 for ( z = 0; z < BIGD_MAXDRIVES; z++ )
2845 {
2846 if ( padapter->raidData )
2847 outb_p (padapter->raidData[z]->status, padapter->regScratchPad + BIGD_RAID_0_STATUS + z);
2848 else
2849 outb_p (0, padapter->regScratchPad + BIGD_RAID_0_STATUS);
2850 }
2851 }
2852 else
2853 {
2854 outb_p (padapter->device[0].DiskMirror[0].status, padapter->regScratchPad + DALE_RAID_0_STATUS);
2855 outb_p (padapter->device[0].DiskMirror[1].status, padapter->regScratchPad + DALE_RAID_1_STATUS);
2856 }
2857
2858 if ( padapter->irqOwned )
2859 free_irq (pshost->irq, padapter);
2860 release_region (pshost->io_port, pshost->n_io_port);
2861 if ( padapter->numberOfDrives )
2862 pci_free_consistent (padapter->pcidev, SECTORSXFER * BYTES_PER_SECTOR, padapter->kBuffer, padapter->kBufferDma);
2863 else
2864 pci_free_consistent (padapter->pcidev, ATAPI_TRANSFER, padapter->kBuffer, padapter->kBufferDma);
2865 scsi_unregister(pshost);
2866 return 0;
2867 }
2868
2869/****************************************************************
2870 * Name: Pci2220i_BiosParam
2871 *
2872 * Description: Process the biosparam request from the SCSI manager to
2873 * return C/H/S data.
2874 *
2875 * Parameters: disk - Pointer to SCSI disk structure.
2876 * dev - Major/minor number from kernel.
2877 * geom - Pointer to integer array to place geometry data.
2878 *
2879 * Returns: zero.
2880 *
2881 ****************************************************************/
2882int Pci2220i_BiosParam (struct scsi_device *sdev, struct block_device *dev,
2883 sector_t capacity, int geom[])
2884 {
2885 POUR_DEVICE pdev;
2886
2887 if ( !(HOSTDATA(sdev->host))->atapi )
2888 {
2889 pdev = &(HOSTDATA(sdev->host)->device[sdev->id]);
2890
2891 geom[0] = pdev->heads;
2892 geom[1] = pdev->sectors;
2893 geom[2] = pdev->cylinders;
2894 }
2895 return 0;
2896 }
2897
2898MODULE_LICENSE("Dual BSD/GPL");
2899
2900static Scsi_Host_Template driver_template = {
2901 .proc_name = "pci2220i",
2902 .name = "PCI-2220I/PCI-2240I",
2903 .detect = Pci2220i_Detect,
2904 .release = Pci2220i_Release,
2905 .queuecommand = Pci2220i_QueueCommand,
2906 .abort = Pci2220i_Abort,
2907 .reset = Pci2220i_Reset,
2908 .bios_param = Pci2220i_BiosParam,
2909 .can_queue = 1,
2910 .this_id = -1,
2911 .sg_tablesize = SG_ALL,
2912 .cmd_per_lun = 1,
2913 .use_clustering = DISABLE_CLUSTERING,
2914};
2915#include "scsi_module.c"