forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 1
/
aic7xxx_old.c
11165 lines (10420 loc) · 358 KB
/
aic7xxx_old.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*+M*************************************************************************
* Adaptec AIC7xxx device driver for Linux.
*
* Copyright (c) 1994 John Aycock
* The University of Calgary Department of Computer Science.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Sources include the Adaptec 1740 driver (aha1740.c), the Ultrastor 24F
* driver (ultrastor.c), various Linux kernel source, the Adaptec EISA
* config file (!adp7771.cfg), the Adaptec AHA-2740A Series User's Guide,
* the Linux Kernel Hacker's Guide, Writing a SCSI Device Driver for Linux,
* the Adaptec 1542 driver (aha1542.c), the Adaptec EISA overlay file
* (adp7770.ovl), the Adaptec AHA-2740 Series Technical Reference Manual,
* the Adaptec AIC-7770 Data Book, the ANSI SCSI specification, the
* ANSI SCSI-2 specification (draft 10c), ...
*
* --------------------------------------------------------------------------
*
* Modifications by Daniel M. Eischen ([email protected]):
*
* Substantially modified to include support for wide and twin bus
* adapters, DMAing of SCBs, tagged queueing, IRQ sharing, bug fixes,
* SCB paging, and other rework of the code.
*
* Parts of this driver were also based on the FreeBSD driver by
* Justin T. Gibbs. His copyright follows:
*
* --------------------------------------------------------------------------
* Copyright (c) 1994-1997 Justin Gibbs.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification, immediately at the beginning of the file.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* Where this Software is combined with software released under the terms of
* the GNU General Public License ("GPL") and the terms of the GPL would require the
* combined work to also be released under the terms of the GPL, the terms
* and conditions of this License will apply in addition to those of the
* GPL with the exception of any terms or conditions of this License that
* conflict with, or are expressly prohibited by, the GPL.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: aic7xxx.c,v 1.119 1997/06/27 19:39:18 gibbs Exp $
*---------------------------------------------------------------------------
*
* Thanks also go to (in alphabetical order) the following:
*
* Rory Bolt - Sequencer bug fixes
* Jay Estabrook - Initial DEC Alpha support
* Doug Ledford - Much needed abort/reset bug fixes
* Kai Makisara - DMAing of SCBs
*
* A Boot time option was also added for not resetting the scsi bus.
*
* Form: aic7xxx=extended
* aic7xxx=no_reset
* aic7xxx=ultra
* aic7xxx=irq_trigger:[0,1] # 0 edge, 1 level
* aic7xxx=verbose
*
* Daniel M. Eischen, [email protected], 1/23/97
*
* $Id: aic7xxx.c,v 4.1 1997/06/12 08:23:42 deang Exp $
*-M*************************************************************************/
/*+M**************************************************************************
*
* Further driver modifications made by Doug Ledford <[email protected]>
*
* Copyright (c) 1997-1999 Doug Ledford
*
* These changes are released under the same licensing terms as the FreeBSD
* driver written by Justin Gibbs. Please see his Copyright notice above
* for the exact terms and conditions covering my changes as well as the
* warranty statement.
*
* Modifications made to the aic7xxx.c,v 4.1 driver from Dan Eischen include
* but are not limited to:
*
* 1: Import of the latest FreeBSD sequencer code for this driver
* 2: Modification of kernel code to accommodate different sequencer semantics
* 3: Extensive changes throughout kernel portion of driver to improve
* abort/reset processing and error hanndling
* 4: Other work contributed by various people on the Internet
* 5: Changes to printk information and verbosity selection code
* 6: General reliability related changes, especially in IRQ management
* 7: Modifications to the default probe/attach order for supported cards
* 8: SMP friendliness has been improved
*
* Overall, this driver represents a significant departure from the official
* aic7xxx driver released by Dan Eischen in two ways. First, in the code
* itself. A diff between the two version of the driver is now a several
* thousand line diff. Second, in approach to solving the same problem. The
* problem is importing the FreeBSD aic7xxx driver code to linux can be a
* difficult and time consuming process, that also can be error prone. Dan
* Eischen's official driver uses the approach that the linux and FreeBSD
* drivers should be as identical as possible. To that end, his next version
* of this driver will be using a mid-layer code library that he is developing
* to moderate communications between the linux mid-level SCSI code and the
* low level FreeBSD driver. He intends to be able to essentially drop the
* FreeBSD driver into the linux kernel with only a few minor tweaks to some
* include files and the like and get things working, making for fast easy
* imports of the FreeBSD code into linux.
*
* I disagree with Dan's approach. Not that I don't think his way of doing
* things would be nice, easy to maintain, and create a more uniform driver
* between FreeBSD and Linux. I have no objection to those issues. My
* disagreement is on the needed functionality. There simply are certain
* things that are done differently in FreeBSD than linux that will cause
* problems for this driver regardless of any middle ware Dan implements.
* The biggest example of this at the moment is interrupt semantics. Linux
* doesn't provide the same protection techniques as FreeBSD does, nor can
* they be easily implemented in any middle ware code since they would truly
* belong in the kernel proper and would effect all drivers. For the time
* being, I see issues such as these as major stumbling blocks to the
* reliability of code based upon such middle ware. Therefore, I choose to
* use a different approach to importing the FreeBSD code that doesn't
* involve any middle ware type code. My approach is to import the sequencer
* code from FreeBSD wholesale. Then, to only make changes in the kernel
* portion of the driver as they are needed for the new sequencer semantics.
* In this way, the portion of the driver that speaks to the rest of the
* linux kernel is fairly static and can be changed/modified to solve
* any problems one might encounter without concern for the FreeBSD driver.
*
* Note: If time and experience should prove me wrong that the middle ware
* code Dan writes is reliable in its operation, then I'll retract my above
* statements. But, for those that don't know, I'm from Missouri (in the US)
* and our state motto is "The Show-Me State". Well, before I will put
* faith into it, you'll have to show me that it works :)
*
*_M*************************************************************************/
/*
* The next three defines are user configurable. These should be the only
* defines a user might need to get in here and change. There are other
* defines buried deeper in the code, but those really shouldn't need touched
* under normal conditions.
*/
/*
* AIC7XXX_STRICT_PCI_SETUP
* Should we assume the PCI config options on our controllers are set with
* sane and proper values, or should we be anal about our PCI config
* registers and force them to what we want? The main advantage to
* defining this option is on non-Intel hardware where the BIOS may not
* have been run to set things up, or if you have one of the BIOSless
* Adaptec controllers, such as a 2910, that don't get set up by the
* BIOS. However, keep in mind that we really do set the most important
* items in the driver regardless of this setting, this only controls some
* of the more esoteric PCI options on these cards. In that sense, I
* would default to leaving this off. However, if people wish to try
* things both ways, that would also help me to know if there are some
* machines where it works one way but not another.
*
* -- July 7, 17:09
* OK...I need this on my machine for testing, so the default is to
* leave it defined.
*
* -- July 7, 18:49
* I needed it for testing, but it didn't make any difference, so back
* off she goes.
*
* -- July 16, 23:04
* I turned it back on to try and compensate for the 2.1.x PCI code
* which no longer relies solely on the BIOS and now tries to set
* things itself.
*/
#define AIC7XXX_STRICT_PCI_SETUP
/*
* AIC7XXX_VERBOSE_DEBUGGING
* This option enables a lot of extra printk();s in the code, surrounded
* by if (aic7xxx_verbose ...) statements. Executing all of those if
* statements and the extra checks can get to where it actually does have
* an impact on CPU usage and such, as well as code size. Disabling this
* define will keep some of those from becoming part of the code.
*
* NOTE: Currently, this option has no real effect, I will be adding the
* various #ifdef's in the code later when I've decided a section is
* complete and no longer needs debugging. OK...a lot of things are now
* surrounded by this define, so turning this off does have an impact.
*/
/*
* #define AIC7XXX_VERBOSE_DEBUGGING
*/
#include <linux/module.h>
#include <stdarg.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/byteorder.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/proc_fs.h>
#include <linux/blkdev.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/smp.h>
#include <linux/interrupt.h>
#include "scsi.h"
#include <scsi/scsi_host.h>
#include "aic7xxx_old/aic7xxx.h"
#include "aic7xxx_old/sequencer.h"
#include "aic7xxx_old/scsi_message.h"
#include "aic7xxx_old/aic7xxx_reg.h"
#include <scsi/scsicam.h>
#include <linux/stat.h>
#include <linux/slab.h> /* for kmalloc() */
#define AIC7XXX_C_VERSION "5.2.6"
#define ALL_TARGETS -1
#define ALL_CHANNELS -1
#define ALL_LUNS -1
#define MAX_TARGETS 16
#define MAX_LUNS 8
#ifndef TRUE
# define TRUE 1
#endif
#ifndef FALSE
# define FALSE 0
#endif
#if defined(__powerpc__) || defined(__i386__) || defined(__x86_64__)
# define MMAPIO
#endif
/*
* You can try raising me for better performance or lowering me if you have
* flaky devices that go off the scsi bus when hit with too many tagged
* commands (like some IBM SCSI-3 LVD drives).
*/
#define AIC7XXX_CMDS_PER_DEVICE 32
typedef struct
{
unsigned char tag_commands[16]; /* Allow for wide/twin adapters. */
} adapter_tag_info_t;
/*
* Make a define that will tell the driver not to the default tag depth
* everywhere.
*/
#define DEFAULT_TAG_COMMANDS {0, 0, 0, 0, 0, 0, 0, 0,\
0, 0, 0, 0, 0, 0, 0, 0}
/*
* Modify this as you see fit for your system. By setting tag_commands
* to 0, the driver will use it's own algorithm for determining the
* number of commands to use (see above). When 255, the driver will
* not enable tagged queueing for that particular device. When positive
* (> 0) and (< 255) the values in the array are used for the queue_depth.
* Note that the maximum value for an entry is 254, but you're insane if
* you try to use that many commands on one device.
*
* In this example, the first line will disable tagged queueing for all
* the devices on the first probed aic7xxx adapter.
*
* The second line enables tagged queueing with 4 commands/LUN for IDs
* (1, 2-11, 13-15), disables tagged queueing for ID 12, and tells the
* driver to use its own algorithm for ID 1.
*
* The third line is the same as the first line.
*
* The fourth line disables tagged queueing for devices 0 and 3. It
* enables tagged queueing for the other IDs, with 16 commands/LUN
* for IDs 1 and 4, 127 commands/LUN for ID 8, and 4 commands/LUN for
* IDs 2, 5-7, and 9-15.
*/
/*
* NOTE: The below structure is for reference only, the actual structure
* to modify in order to change things is found after this fake one.
*
adapter_tag_info_t aic7xxx_tag_info[] =
{
{DEFAULT_TAG_COMMANDS},
{{4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 255, 4, 4, 4}},
{DEFAULT_TAG_COMMANDS},
{{255, 16, 4, 255, 16, 4, 4, 4, 127, 4, 4, 4, 4, 4, 4, 4}}
};
*/
static adapter_tag_info_t aic7xxx_tag_info[] =
{
{DEFAULT_TAG_COMMANDS},
{DEFAULT_TAG_COMMANDS},
{DEFAULT_TAG_COMMANDS},
{DEFAULT_TAG_COMMANDS},
{DEFAULT_TAG_COMMANDS},
{DEFAULT_TAG_COMMANDS},
{DEFAULT_TAG_COMMANDS},
{DEFAULT_TAG_COMMANDS},
{DEFAULT_TAG_COMMANDS},
{DEFAULT_TAG_COMMANDS},
{DEFAULT_TAG_COMMANDS},
{DEFAULT_TAG_COMMANDS},
{DEFAULT_TAG_COMMANDS},
{DEFAULT_TAG_COMMANDS},
{DEFAULT_TAG_COMMANDS},
{DEFAULT_TAG_COMMANDS}
};
/*
* Define an array of board names that can be indexed by aha_type.
* Don't forget to change this when changing the types!
*/
static const char *board_names[] = {
"AIC-7xxx Unknown", /* AIC_NONE */
"Adaptec AIC-7810 Hardware RAID Controller", /* AIC_7810 */
"Adaptec AIC-7770 SCSI host adapter", /* AIC_7770 */
"Adaptec AHA-274X SCSI host adapter", /* AIC_7771 */
"Adaptec AHA-284X SCSI host adapter", /* AIC_284x */
"Adaptec AIC-7850 SCSI host adapter", /* AIC_7850 */
"Adaptec AIC-7855 SCSI host adapter", /* AIC_7855 */
"Adaptec AIC-7860 Ultra SCSI host adapter", /* AIC_7860 */
"Adaptec AHA-2940A Ultra SCSI host adapter", /* AIC_7861 */
"Adaptec AIC-7870 SCSI host adapter", /* AIC_7870 */
"Adaptec AHA-294X SCSI host adapter", /* AIC_7871 */
"Adaptec AHA-394X SCSI host adapter", /* AIC_7872 */
"Adaptec AHA-398X SCSI host adapter", /* AIC_7873 */
"Adaptec AHA-2944 SCSI host adapter", /* AIC_7874 */
"Adaptec AIC-7880 Ultra SCSI host adapter", /* AIC_7880 */
"Adaptec AHA-294X Ultra SCSI host adapter", /* AIC_7881 */
"Adaptec AHA-394X Ultra SCSI host adapter", /* AIC_7882 */
"Adaptec AHA-398X Ultra SCSI host adapter", /* AIC_7883 */
"Adaptec AHA-2944 Ultra SCSI host adapter", /* AIC_7884 */
"Adaptec AHA-2940UW Pro Ultra SCSI host adapter", /* AIC_7887 */
"Adaptec AIC-7895 Ultra SCSI host adapter", /* AIC_7895 */
"Adaptec AIC-7890/1 Ultra2 SCSI host adapter", /* AIC_7890 */
"Adaptec AHA-293X Ultra2 SCSI host adapter", /* AIC_7890 */
"Adaptec AHA-294X Ultra2 SCSI host adapter", /* AIC_7890 */
"Adaptec AIC-7896/7 Ultra2 SCSI host adapter", /* AIC_7896 */
"Adaptec AHA-394X Ultra2 SCSI host adapter", /* AIC_7897 */
"Adaptec AHA-395X Ultra2 SCSI host adapter", /* AIC_7897 */
"Adaptec PCMCIA SCSI controller", /* card bus stuff */
"Adaptec AIC-7892 Ultra 160/m SCSI host adapter", /* AIC_7892 */
"Adaptec AIC-7899 Ultra 160/m SCSI host adapter", /* AIC_7899 */
};
/*
* There should be a specific return value for this in scsi.h, but
* it seems that most drivers ignore it.
*/
#define DID_UNDERFLOW DID_ERROR
/*
* What we want to do is have the higher level scsi driver requeue
* the command to us. There is no specific driver status for this
* condition, but the higher level scsi driver will requeue the
* command on a DID_BUS_BUSY error.
*
* Upon further inspection and testing, it seems that DID_BUS_BUSY
* will *always* retry the command. We can get into an infinite loop
* if this happens when we really want some sort of counter that
* will automatically abort/reset the command after so many retries.
* Using DID_ERROR will do just that. (Made by a suggestion by
* Doug Ledford 8/1/96)
*/
#define DID_RETRY_COMMAND DID_ERROR
#define HSCSIID 0x07
#define SCSI_RESET 0x040
/*
* EISA/VL-bus stuff
*/
#define MINSLOT 1
#define MAXSLOT 15
#define SLOTBASE(x) ((x) << 12)
#define BASE_TO_SLOT(x) ((x) >> 12)
/*
* Standard EISA Host ID regs (Offset from slot base)
*/
#define AHC_HID0 0x80 /* 0,1: msb of ID2, 2-7: ID1 */
#define AHC_HID1 0x81 /* 0-4: ID3, 5-7: LSB ID2 */
#define AHC_HID2 0x82 /* product */
#define AHC_HID3 0x83 /* firmware revision */
/*
* AIC-7770 I/O range to reserve for a card
*/
#define MINREG 0xC00
#define MAXREG 0xCFF
#define INTDEF 0x5C /* Interrupt Definition Register */
/*
* AIC-78X0 PCI registers
*/
#define CLASS_PROGIF_REVID 0x08
#define DEVREVID 0x000000FFul
#define PROGINFC 0x0000FF00ul
#define SUBCLASS 0x00FF0000ul
#define BASECLASS 0xFF000000ul
#define CSIZE_LATTIME 0x0C
#define CACHESIZE 0x0000003Ful /* only 5 bits */
#define LATTIME 0x0000FF00ul
#define DEVCONFIG 0x40
#define SCBSIZE32 0x00010000ul /* aic789X only */
#define MPORTMODE 0x00000400ul /* aic7870 only */
#define RAMPSM 0x00000200ul /* aic7870 only */
#define RAMPSM_ULTRA2 0x00000004
#define VOLSENSE 0x00000100ul
#define SCBRAMSEL 0x00000080ul
#define SCBRAMSEL_ULTRA2 0x00000008
#define MRDCEN 0x00000040ul
#define EXTSCBTIME 0x00000020ul /* aic7870 only */
#define EXTSCBPEN 0x00000010ul /* aic7870 only */
#define BERREN 0x00000008ul
#define DACEN 0x00000004ul
#define STPWLEVEL 0x00000002ul
#define DIFACTNEGEN 0x00000001ul /* aic7870 only */
#define SCAMCTL 0x1a /* Ultra2 only */
#define CCSCBBADDR 0xf0 /* aic7895/6/7 */
/*
* Define the different types of SEEPROMs on aic7xxx adapters
* and make it also represent the address size used in accessing
* its registers. The 93C46 chips have 1024 bits organized into
* 64 16-bit words, while the 93C56 chips have 2048 bits organized
* into 128 16-bit words. The C46 chips use 6 bits to address
* each word, while the C56 and C66 (4096 bits) use 8 bits to
* address each word.
*/
typedef enum {C46 = 6, C56_66 = 8} seeprom_chip_type;
/*
*
* Define the format of the SEEPROM registers (16 bits).
*
*/
struct seeprom_config {
/*
* SCSI ID Configuration Flags
*/
#define CFXFER 0x0007 /* synchronous transfer rate */
#define CFSYNCH 0x0008 /* enable synchronous transfer */
#define CFDISC 0x0010 /* enable disconnection */
#define CFWIDEB 0x0020 /* wide bus device (wide card) */
#define CFSYNCHISULTRA 0x0040 /* CFSYNC is an ultra offset */
#define CFNEWULTRAFORMAT 0x0080 /* Use the Ultra2 SEEPROM format */
#define CFSTART 0x0100 /* send start unit SCSI command */
#define CFINCBIOS 0x0200 /* include in BIOS scan */
#define CFRNFOUND 0x0400 /* report even if not found */
#define CFMULTILUN 0x0800 /* probe mult luns in BIOS scan */
#define CFWBCACHEYES 0x4000 /* Enable W-Behind Cache on drive */
#define CFWBCACHENC 0xc000 /* Don't change W-Behind Cache */
/* UNUSED 0x3000 */
unsigned short device_flags[16]; /* words 0-15 */
/*
* BIOS Control Bits
*/
#define CFSUPREM 0x0001 /* support all removable drives */
#define CFSUPREMB 0x0002 /* support removable drives for boot only */
#define CFBIOSEN 0x0004 /* BIOS enabled */
/* UNUSED 0x0008 */
#define CFSM2DRV 0x0010 /* support more than two drives */
#define CF284XEXTEND 0x0020 /* extended translation (284x cards) */
/* UNUSED 0x0040 */
#define CFEXTEND 0x0080 /* extended translation enabled */
/* UNUSED 0xFF00 */
unsigned short bios_control; /* word 16 */
/*
* Host Adapter Control Bits
*/
#define CFAUTOTERM 0x0001 /* Perform Auto termination */
#define CFULTRAEN 0x0002 /* Ultra SCSI speed enable (Ultra cards) */
#define CF284XSELTO 0x0003 /* Selection timeout (284x cards) */
#define CF284XFIFO 0x000C /* FIFO Threshold (284x cards) */
#define CFSTERM 0x0004 /* SCSI low byte termination */
#define CFWSTERM 0x0008 /* SCSI high byte termination (wide card) */
#define CFSPARITY 0x0010 /* SCSI parity */
#define CF284XSTERM 0x0020 /* SCSI low byte termination (284x cards) */
#define CFRESETB 0x0040 /* reset SCSI bus at boot */
#define CFBPRIMARY 0x0100 /* Channel B primary on 7895 chipsets */
#define CFSEAUTOTERM 0x0400 /* aic7890 Perform SE Auto Term */
#define CFLVDSTERM 0x0800 /* aic7890 LVD Termination */
/* UNUSED 0xF280 */
unsigned short adapter_control; /* word 17 */
/*
* Bus Release, Host Adapter ID
*/
#define CFSCSIID 0x000F /* host adapter SCSI ID */
/* UNUSED 0x00F0 */
#define CFBRTIME 0xFF00 /* bus release time */
unsigned short brtime_id; /* word 18 */
/*
* Maximum targets
*/
#define CFMAXTARG 0x00FF /* maximum targets */
/* UNUSED 0xFF00 */
unsigned short max_targets; /* word 19 */
unsigned short res_1[11]; /* words 20-30 */
unsigned short checksum; /* word 31 */
};
#define SELBUS_MASK 0x0a
#define SELNARROW 0x00
#define SELBUSB 0x08
#define SINGLE_BUS 0x00
#define SCB_TARGET(scb) \
(((scb)->hscb->target_channel_lun & TID) >> 4)
#define SCB_LUN(scb) \
((scb)->hscb->target_channel_lun & LID)
#define SCB_IS_SCSIBUS_B(scb) \
(((scb)->hscb->target_channel_lun & SELBUSB) != 0)
/*
* If an error occurs during a data transfer phase, run the command
* to completion - it's easier that way - making a note of the error
* condition in this location. This then will modify a DID_OK status
* into an appropriate error for the higher-level SCSI code.
*/
#define aic7xxx_error(cmd) ((cmd)->SCp.Status)
/*
* Keep track of the targets returned status.
*/
#define aic7xxx_status(cmd) ((cmd)->SCp.sent_command)
/*
* The position of the SCSI commands scb within the scb array.
*/
#define aic7xxx_position(cmd) ((cmd)->SCp.have_data_in)
/*
* The stored DMA mapping for single-buffer data transfers.
*/
#define aic7xxx_mapping(cmd) ((cmd)->SCp.phase)
/*
* Get out private data area from a scsi cmd pointer
*/
#define AIC_DEV(cmd) ((struct aic_dev_data *)(cmd)->device->hostdata)
/*
* So we can keep track of our host structs
*/
static struct aic7xxx_host *first_aic7xxx = NULL;
/*
* As of Linux 2.1, the mid-level SCSI code uses virtual addresses
* in the scatter-gather lists. We need to convert the virtual
* addresses to physical addresses.
*/
struct hw_scatterlist {
unsigned int address;
unsigned int length;
};
/*
* Maximum number of SG segments these cards can support.
*/
#define AIC7XXX_MAX_SG 128
/*
* The maximum number of SCBs we could have for ANY type
* of card. DON'T FORGET TO CHANGE THE SCB MASK IN THE
* SEQUENCER CODE IF THIS IS MODIFIED!
*/
#define AIC7XXX_MAXSCB 255
struct aic7xxx_hwscb {
/* ------------ Begin hardware supported fields ---------------- */
/* 0*/ unsigned char control;
/* 1*/ unsigned char target_channel_lun; /* 4/1/3 bits */
/* 2*/ unsigned char target_status;
/* 3*/ unsigned char SG_segment_count;
/* 4*/ unsigned int SG_list_pointer;
/* 8*/ unsigned char residual_SG_segment_count;
/* 9*/ unsigned char residual_data_count[3];
/*12*/ unsigned int data_pointer;
/*16*/ unsigned int data_count;
/*20*/ unsigned int SCSI_cmd_pointer;
/*24*/ unsigned char SCSI_cmd_length;
/*25*/ unsigned char tag; /* Index into our kernel SCB array.
* Also used as the tag for tagged I/O
*/
#define SCB_PIO_TRANSFER_SIZE 26 /* amount we need to upload/download
* via PIO to initialize a transaction.
*/
/*26*/ unsigned char next; /* Used to thread SCBs awaiting selection
* or disconnected down in the sequencer.
*/
/*27*/ unsigned char prev;
/*28*/ unsigned int pad; /*
* Unused by the kernel, but we require
* the padding so that the array of
* hardware SCBs is aligned on 32 byte
* boundaries so the sequencer can index
*/
};
typedef enum {
SCB_FREE = 0x0000,
SCB_DTR_SCB = 0x0001,
SCB_WAITINGQ = 0x0002,
SCB_ACTIVE = 0x0004,
SCB_SENSE = 0x0008,
SCB_ABORT = 0x0010,
SCB_DEVICE_RESET = 0x0020,
SCB_RESET = 0x0040,
SCB_RECOVERY_SCB = 0x0080,
SCB_MSGOUT_PPR = 0x0100,
SCB_MSGOUT_SENT = 0x0200,
SCB_MSGOUT_SDTR = 0x0400,
SCB_MSGOUT_WDTR = 0x0800,
SCB_MSGOUT_BITS = SCB_MSGOUT_PPR |
SCB_MSGOUT_SENT |
SCB_MSGOUT_SDTR |
SCB_MSGOUT_WDTR,
SCB_QUEUED_ABORT = 0x1000,
SCB_QUEUED_FOR_DONE = 0x2000,
SCB_WAS_BUSY = 0x4000,
SCB_QUEUE_FULL = 0x8000
} scb_flag_type;
typedef enum {
AHC_FNONE = 0x00000000,
AHC_PAGESCBS = 0x00000001,
AHC_CHANNEL_B_PRIMARY = 0x00000002,
AHC_USEDEFAULTS = 0x00000004,
AHC_INDIRECT_PAGING = 0x00000008,
AHC_CHNLB = 0x00000020,
AHC_CHNLC = 0x00000040,
AHC_EXTEND_TRANS_A = 0x00000100,
AHC_EXTEND_TRANS_B = 0x00000200,
AHC_TERM_ENB_A = 0x00000400,
AHC_TERM_ENB_SE_LOW = 0x00000400,
AHC_TERM_ENB_B = 0x00000800,
AHC_TERM_ENB_SE_HIGH = 0x00000800,
AHC_HANDLING_REQINITS = 0x00001000,
AHC_TARGETMODE = 0x00002000,
AHC_NEWEEPROM_FMT = 0x00004000,
/*
* Here ends the FreeBSD defined flags and here begins the linux defined
* flags. NOTE: I did not preserve the old flag name during this change
* specifically to force me to evaluate what flags were being used properly
* and what flags weren't. This way, I could clean up the flag usage on
* a use by use basis. Doug Ledford
*/
AHC_MOTHERBOARD = 0x00020000,
AHC_NO_STPWEN = 0x00040000,
AHC_RESET_DELAY = 0x00080000,
AHC_A_SCANNED = 0x00100000,
AHC_B_SCANNED = 0x00200000,
AHC_MULTI_CHANNEL = 0x00400000,
AHC_BIOS_ENABLED = 0x00800000,
AHC_SEEPROM_FOUND = 0x01000000,
AHC_TERM_ENB_LVD = 0x02000000,
AHC_ABORT_PENDING = 0x04000000,
AHC_RESET_PENDING = 0x08000000,
#define AHC_IN_ISR_BIT 28
AHC_IN_ISR = 0x10000000,
AHC_IN_ABORT = 0x20000000,
AHC_IN_RESET = 0x40000000,
AHC_EXTERNAL_SRAM = 0x80000000
} ahc_flag_type;
typedef enum {
AHC_NONE = 0x0000,
AHC_CHIPID_MASK = 0x00ff,
AHC_AIC7770 = 0x0001,
AHC_AIC7850 = 0x0002,
AHC_AIC7860 = 0x0003,
AHC_AIC7870 = 0x0004,
AHC_AIC7880 = 0x0005,
AHC_AIC7890 = 0x0006,
AHC_AIC7895 = 0x0007,
AHC_AIC7896 = 0x0008,
AHC_AIC7892 = 0x0009,
AHC_AIC7899 = 0x000a,
AHC_VL = 0x0100,
AHC_EISA = 0x0200,
AHC_PCI = 0x0400,
} ahc_chip;
typedef enum {
AHC_FENONE = 0x0000,
AHC_ULTRA = 0x0001,
AHC_ULTRA2 = 0x0002,
AHC_WIDE = 0x0004,
AHC_TWIN = 0x0008,
AHC_MORE_SRAM = 0x0010,
AHC_CMD_CHAN = 0x0020,
AHC_QUEUE_REGS = 0x0040,
AHC_SG_PRELOAD = 0x0080,
AHC_SPIOCAP = 0x0100,
AHC_ULTRA3 = 0x0200,
AHC_NEW_AUTOTERM = 0x0400,
AHC_AIC7770_FE = AHC_FENONE,
AHC_AIC7850_FE = AHC_SPIOCAP,
AHC_AIC7860_FE = AHC_ULTRA|AHC_SPIOCAP,
AHC_AIC7870_FE = AHC_FENONE,
AHC_AIC7880_FE = AHC_ULTRA,
AHC_AIC7890_FE = AHC_MORE_SRAM|AHC_CMD_CHAN|AHC_ULTRA2|
AHC_QUEUE_REGS|AHC_SG_PRELOAD|AHC_NEW_AUTOTERM,
AHC_AIC7895_FE = AHC_MORE_SRAM|AHC_CMD_CHAN|AHC_ULTRA,
AHC_AIC7896_FE = AHC_AIC7890_FE,
AHC_AIC7892_FE = AHC_AIC7890_FE|AHC_ULTRA3,
AHC_AIC7899_FE = AHC_AIC7890_FE|AHC_ULTRA3,
} ahc_feature;
#define SCB_DMA_ADDR(scb, addr) ((unsigned long)(addr) + (scb)->scb_dma->dma_offset)
struct aic7xxx_scb_dma {
unsigned long dma_offset; /* Correction you have to add
* to virtual address to get
* dma handle in this region */
dma_addr_t dma_address; /* DMA handle of the start,
* for unmap */
unsigned int dma_len; /* DMA length */
};
typedef enum {
AHC_BUG_NONE = 0x0000,
AHC_BUG_TMODE_WIDEODD = 0x0001,
AHC_BUG_AUTOFLUSH = 0x0002,
AHC_BUG_CACHETHEN = 0x0004,
AHC_BUG_CACHETHEN_DIS = 0x0008,
AHC_BUG_PCI_2_1_RETRY = 0x0010,
AHC_BUG_PCI_MWI = 0x0020,
AHC_BUG_SCBCHAN_UPLOAD = 0x0040,
} ahc_bugs;
struct aic7xxx_scb {
struct aic7xxx_hwscb *hscb; /* corresponding hardware scb */
struct scsi_cmnd *cmd; /* scsi_cmnd for this scb */
struct aic7xxx_scb *q_next; /* next scb in queue */
volatile scb_flag_type flags; /* current state of scb */
struct hw_scatterlist *sg_list; /* SG list in adapter format */
unsigned char tag_action;
unsigned char sg_count;
unsigned char *sense_cmd; /*
* Allocate 6 characters for
* sense command.
*/
unsigned char *cmnd;
unsigned int sg_length; /*
* We init this during
* buildscb so we don't have
* to calculate anything during
* underflow/overflow/stat code
*/
void *kmalloc_ptr;
struct aic7xxx_scb_dma *scb_dma;
};
/*
* Define a linked list of SCBs.
*/
typedef struct {
struct aic7xxx_scb *head;
struct aic7xxx_scb *tail;
} scb_queue_type;
static struct {
unsigned char errno;
const char *errmesg;
} hard_error[] = {
{ ILLHADDR, "Illegal Host Access" },
{ ILLSADDR, "Illegal Sequencer Address referenced" },
{ ILLOPCODE, "Illegal Opcode in sequencer program" },
{ SQPARERR, "Sequencer Ram Parity Error" },
{ DPARERR, "Data-Path Ram Parity Error" },
{ MPARERR, "Scratch Ram/SCB Array Ram Parity Error" },
{ PCIERRSTAT,"PCI Error detected" },
{ CIOPARERR, "CIOBUS Parity Error" }
};
static unsigned char
generic_sense[] = { REQUEST_SENSE, 0, 0, 0, 255, 0 };
typedef struct {
scb_queue_type free_scbs; /*
* SCBs assigned to free slot on
* card (no paging required)
*/
struct aic7xxx_scb *scb_array[AIC7XXX_MAXSCB];
struct aic7xxx_hwscb *hscbs;
unsigned char numscbs; /* current number of scbs */
unsigned char maxhscbs; /* hardware scbs */
unsigned char maxscbs; /* max scbs including pageable scbs */
dma_addr_t hscbs_dma; /* DMA handle to hscbs */
unsigned int hscbs_dma_len; /* length of the above DMA area */
void *hscb_kmalloc_ptr;
} scb_data_type;
struct target_cmd {
unsigned char mesg_bytes[4];
unsigned char command[28];
};
#define AHC_TRANS_CUR 0x0001
#define AHC_TRANS_ACTIVE 0x0002
#define AHC_TRANS_GOAL 0x0004
#define AHC_TRANS_USER 0x0008
#define AHC_TRANS_QUITE 0x0010
typedef struct {
unsigned char width;
unsigned char period;
unsigned char offset;
unsigned char options;
} transinfo_type;
struct aic_dev_data {
volatile scb_queue_type delayed_scbs;
volatile unsigned short temp_q_depth;
unsigned short max_q_depth;
volatile unsigned char active_cmds;
/*
* Statistics Kept:
*
* Total Xfers (count for each command that has a data xfer),
* broken down by reads && writes.
*
* Further sorted into a few bins for keeping tabs on how many commands
* we get of various sizes.
*
*/
long w_total; /* total writes */
long r_total; /* total reads */
long barrier_total; /* total num of REQ_BARRIER commands */
long ordered_total; /* How many REQ_BARRIER commands we
used ordered tags to satisfy */
long w_bins[6]; /* binned write */
long r_bins[6]; /* binned reads */
transinfo_type cur;
transinfo_type goal;
#define BUS_DEVICE_RESET_PENDING 0x01
#define DEVICE_RESET_DELAY 0x02
#define DEVICE_PRINT_DTR 0x04
#define DEVICE_WAS_BUSY 0x08
#define DEVICE_DTR_SCANNED 0x10
#define DEVICE_SCSI_3 0x20
volatile unsigned char flags;
unsigned needppr:1;
unsigned needppr_copy:1;
unsigned needsdtr:1;
unsigned needsdtr_copy:1;
unsigned needwdtr:1;
unsigned needwdtr_copy:1;
unsigned dtr_pending:1;
struct scsi_device *SDptr;
struct list_head list;
};
/*
* Define a structure used for each host adapter. Note, in order to avoid
* problems with architectures I can't test on (because I don't have one,
* such as the Alpha based systems) which happen to give faults for
* non-aligned memory accesses, care was taken to align this structure
* in a way that gauranteed all accesses larger than 8 bits were aligned
* on the appropriate boundary. It's also organized to try and be more
* cache line efficient. Be careful when changing this lest you might hurt
* overall performance and bring down the wrath of the masses.
*/
struct aic7xxx_host {
/*
* This is the first 64 bytes in the host struct
*/
/*
* We are grouping things here....first, items that get either read or
* written with nearly every interrupt
*/
volatile long flags;
ahc_feature features; /* chip features */
unsigned long base; /* card base address */
volatile unsigned char __iomem *maddr; /* memory mapped address */
unsigned long isr_count; /* Interrupt count */
unsigned long spurious_int;
scb_data_type *scb_data;
struct aic7xxx_cmd_queue {
struct scsi_cmnd *head;
struct scsi_cmnd *tail;
} completeq;
/*
* Things read/written on nearly every entry into aic7xxx_queue()
*/
volatile scb_queue_type waiting_scbs;
unsigned char unpause; /* unpause value for HCNTRL */
unsigned char pause; /* pause value for HCNTRL */
volatile unsigned char qoutfifonext;
volatile unsigned char activescbs; /* active scbs */
volatile unsigned char max_activescbs;
volatile unsigned char qinfifonext;
volatile unsigned char *untagged_scbs;
volatile unsigned char *qoutfifo;
volatile unsigned char *qinfifo;
unsigned char dev_last_queue_full[MAX_TARGETS];
unsigned char dev_last_queue_full_count[MAX_TARGETS];
unsigned short ultraenb; /* Gets downloaded to card as a bitmap */
unsigned short discenable; /* Gets downloaded to card as a bitmap */
transinfo_type user[MAX_TARGETS];
unsigned char msg_buf[13]; /* The message for the target */
unsigned char msg_type;
#define MSG_TYPE_NONE 0x00
#define MSG_TYPE_INITIATOR_MSGOUT 0x01
#define MSG_TYPE_INITIATOR_MSGIN 0x02
unsigned char msg_len; /* Length of message */
unsigned char msg_index; /* Index into msg_buf array */
/*
* We put the less frequently used host structure items
* after the more frequently used items to try and ease
* the burden on the cache subsystem.
* These entries are not *commonly* accessed, whereas
* the preceding entries are accessed very often.
*/
unsigned int irq; /* IRQ for this adapter */
int instance; /* aic7xxx instance number */
int scsi_id; /* host adapter SCSI ID */
int scsi_id_b; /* channel B for twin adapters */
unsigned int bios_address;
int board_name_index;
unsigned short bios_control; /* bios control - SEEPROM */
unsigned short adapter_control; /* adapter control - SEEPROM */
struct pci_dev *pdev;
unsigned char pci_bus;
unsigned char pci_device_fn;
struct seeprom_config sc;
unsigned short sc_type;
unsigned short sc_size;
struct aic7xxx_host *next; /* allow for multiple IRQs */
struct Scsi_Host *host; /* pointer to scsi host */
struct list_head aic_devs; /* all aic_dev structs on host */
int host_no; /* SCSI host number */
unsigned long mbase; /* I/O memory address */
ahc_chip chip; /* chip type */
ahc_bugs bugs;
dma_addr_t fifo_dma; /* DMA handle for fifo arrays */
};
/*
* Valid SCSIRATE values. (p. 3-17)
* Provides a mapping of transfer periods in ns/4 to the proper value to
* stick in the SCSIRATE reg to use that transfer rate.
*/
#define AHC_SYNCRATE_ULTRA3 0