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#include <linux/config.h>
581#include <linux/version.h>
582#include <linux/module.h>
583#include <linux/types.h>
584#include <linux/errno.h>
585#include <linux/string.h>
586#include <linux/kernel.h>
587#include <linux/ioport.h>
588#include <linux/fcntl.h>
589#include <linux/delay.h>
590#include <linux/pci.h>
591#include <linux/proc_fs.h>
592#include <linux/blk.h>
593#include <linux/wait.h>
594#include <linux/tqueue.h>
595#include <linux/interrupt.h>
596#include <linux/mm.h>
597#include <asm/pgtable.h>
598
599#include <linux/sched.h>
600#include <linux/stat.h>
601#include <linux/slab.h>
602#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
603#include <linux/bios32.h>
604#else
605#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
606#include <asm/spinlock.h>
607#else
608#include <linux/spinlock.h>
609#endif
610#endif
611
612#include <asm/io.h>
613#include <asm/irq.h>
614
615#if LINUX_VERSION_CODE > KERNEL_VERSION(2,0,24)
616#include <asm/uaccess.h>
617#endif
618
619
620
621
622#include <linux/notifier.h>
623#include <linux/reboot.h>
624#include <linux/init.h>
625
626#ifdef __x86_64__
627#include <asm/ioctl32.h>
628#endif
629
630#include "sd.h"
631#include "scsi.h"
632#include "hosts.h"
633
634#include "megaraid.h"
635
636#ifdef __x86_64__
637
638
639
640
641extern int register_ioctl32_conversion( unsigned int cmd,
642 int(*handler)(unsigned int, unsigned int, unsigned long,
643 struct file* ));
644extern int unregister_ioctl32_conversion( unsigned int cmd );
645#endif
646
647
648
649
650
651
652
653#define MAX_SERBUF 160
654#define COM_BASE 0x2f8
655
656static ulong RDINDOOR (mega_host_config * megaCfg)
657{
658 return readl (megaCfg->base + 0x20);
659}
660
661static void WRINDOOR (mega_host_config * megaCfg, ulong value)
662{
663 writel (value, megaCfg->base + 0x20);
664}
665
666static ulong RDOUTDOOR (mega_host_config * megaCfg)
667{
668 return readl (megaCfg->base + 0x2C);
669}
670
671static void WROUTDOOR (mega_host_config * megaCfg, ulong value)
672{
673 writel (value, megaCfg->base + 0x2C);
674}
675
676#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
677#include <linux/smp.h>
678#define cpuid smp_processor_id()
679#endif
680
681#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4)
682#define scsi_set_pci_device(x,y)
683#endif
684
685#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
686
687
688
689
690
691
692
693
694
695MODULE_AUTHOR ("LSI Logic Corporation");
696MODULE_DESCRIPTION ("LSI Logic MegaRAID driver");
697MODULE_LICENSE ("GPL");
698
699#define DRIVER_LOCK_T
700#define DRIVER_LOCK_INIT(p)
701#define DRIVER_LOCK(p)
702#define DRIVER_UNLOCK(p)
703#define IO_LOCK_T unsigned long io_flags = 0
704#define IO_LOCK spin_lock_irqsave(&io_request_lock,io_flags);
705#define IO_UNLOCK spin_unlock_irqrestore(&io_request_lock,io_flags);
706
707#define queue_task_irq(a,b) queue_task(a,b)
708#define queue_task_irq_off(a,b) queue_task(a,b)
709
710#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
711
712
713
714
715
716
717
718
719
720
721static char kernel_version[] = UTS_RELEASE;
722MODULE_AUTHOR ("LSI Logic Corporation");
723MODULE_DESCRIPTION ("LSI Logic MegaRAID driver");
724
725#define DRIVER_LOCK_T
726#define DRIVER_LOCK_INIT(p)
727#define DRIVER_LOCK(p)
728#define DRIVER_UNLOCK(p)
729#define IO_LOCK_T unsigned long io_flags = 0
730#define IO_LOCK spin_lock_irqsave(&io_request_lock,io_flags);
731#define IO_UNLOCK spin_unlock_irqrestore(&io_request_lock,io_flags);
732
733#define pci_free_consistent(a,b,c,d)
734#define pci_unmap_single(a,b,c,d)
735#define pci_enable_device(x) (0)
736#define queue_task_irq(a,b) queue_task(a,b)
737#define queue_task_irq_off(a,b) queue_task(a,b)
738
739#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,19)
740#define init_MUTEX_LOCKED(x) (*(x)=MUTEX_LOCKED)
741#define init_MUTEX(x) (*(x)=MUTEX)
742#define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue *x = NULL
743#endif
744
745
746#else
747
748
749
750
751
752
753
754
755#define cpuid 0
756#define DRIVER_LOCK_T long cpu_flags;
757#define DRIVER_LOCK_INIT(p)
758#define DRIVER_LOCK(p) \
759 save_flags(cpu_flags); \
760 cli();
761#define DRIVER_UNLOCK(p) \
762 restore_flags(cpu_flags);
763#define IO_LOCK_T
764#define IO_LOCK(p)
765#define IO_UNLOCK(p)
766#define le32_to_cpu(x) (x)
767#define cpu_to_le32(x) (x)
768
769#define pci_free_consistent(a,b,c,d)
770#define pci_unmap_single(a,b,c,d)
771
772#define init_MUTEX_LOCKED(x) (*(x)=MUTEX_LOCKED)
773#define init_MUTEX(x) (*(x)=MUTEX)
774
775#define pci_enable_device(x) (0)
776
777
778
779
780
781#define ioremap vremap
782#define iounmap vfree
783
784
785typedef struct {
786 volatile char lock;
787} spinlock_t;
788
789#define spin_lock_init(x) { (x)->lock = 0;}
790#define spin_lock_irqsave(x,flags) { while ((x)->lock) barrier();\
791 (x)->lock=1; save_flags(flags);\
792 cli();}
793#define spin_unlock_irqrestore(x,flags) { (x)->lock=0; restore_flags(flags);}
794
795#define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue *x = NULL
796
797#endif
798
799
800#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
801#define dma_alloc_consistent pci_alloc_consistent
802#define dma_free_consistent pci_free_consistent
803#else
804#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,19)
805typedef unsigned long dma_addr_t;
806#endif
807void *dma_alloc_consistent(void *, size_t, dma_addr_t *);
808void dma_free_consistent(void *, size_t, void *, dma_addr_t);
809int mega_get_order(int);
810int pow_2(int);
811#endif
812
813
814#define SERDEBUG 0
815#if SERDEBUG
816static void ser_init (void);
817static void ser_puts (char *str);
818static void ser_putc (char c);
819static int ser_printk (const char *fmt, ...);
820#endif
821
822#ifdef CONFIG_PROC_FS
823#define COPY_BACK if (offset > megaCfg->procidx) { \
824 *eof = TRUE; \
825 megaCfg->procidx = 0; \
826 megaCfg->procbuf[0] = 0; \
827 return 0;} \
828 if ((count + offset) > megaCfg->procidx) { \
829 count = megaCfg->procidx - offset; \
830 *eof = TRUE; } \
831 memcpy(page, &megaCfg->procbuf[offset], count); \
832 megaCfg->procidx = 0; \
833 megaCfg->procbuf[0] = 0;
834#endif
835
836
837
838
839
840
841
842
843
844
845
846static char *megaraid;
847#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
848#ifdef MODULE
849MODULE_PARM (megaraid, "s");
850#endif
851#endif
852static int skip_id = -1;
853static int numCtlrs = 0;
854static mega_host_config *megaCtlrs[FC_MAX_CHANNELS] = { 0 };
855static struct proc_dir_entry *mega_proc_dir_entry;
856
857#if DEBUG
858static u32 maxCmdTime = 0;
859#endif
860
861static mega_scb *pLastScb = NULL;
862static struct notifier_block mega_notifier = {
863 megaraid_reboot_notify,
864 NULL,
865 0
866};
867
868
869struct mega_hbas mega_hbas[MAX_CONTROLLERS];
870
871
872
873
874
875
876static struct file_operations megadev_fops = {
877 ioctl:megadev_ioctl_entry,
878 open:megadev_open,
879 release:megadev_close,
880};
881
882
883
884
885
886
887static struct mcontroller mcontroller[MAX_CONTROLLERS];
888
889
890static u32 driver_ver = 0x118C;
891
892
893static int major;
894
895static struct semaphore mimd_ioctl_sem;
896static struct semaphore mimd_entry_mtx;
897
898#if SERDEBUG
899volatile static spinlock_t serial_lock;
900#endif
901
902#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
903static struct proc_dir_entry proc_scsi_megaraid = {
904 PROC_SCSI_MEGARAID, 8, "megaraid",
905 S_IFDIR | S_IRUGO | S_IXUGO, 2
906};
907#endif
908
909#ifdef CONFIG_PROC_FS
910extern struct proc_dir_entry proc_root;
911#endif
912
913#define IS_RAID_CH(this, ch) ( (this->mega_ch_class >> (ch)) & 0x01 )
914
915#if SERDEBUG
916static char strbuf[MAX_SERBUF + 1];
917
918static void ser_init (void)
919{
920 unsigned port = COM_BASE;
921
922 outb (0x80, port + 3);
923 outb (0, port + 1);
924
925 outb (12, port);
926 outb (3, port + 3);
927 outb (0, port + 1);
928}
929
930static void ser_puts (char *str)
931{
932 char *ptr;
933
934 ser_init ();
935 for (ptr = str; *ptr; ++ptr)
936 ser_putc (*ptr);
937}
938
939static void ser_putc (char c)
940{
941 unsigned port = COM_BASE;
942
943 while ((inb (port + 5) & 0x20) == 0) ;
944 outb (c, port);
945 if (c == 0x0a) {
946 while ((inb (port + 5) & 0x20) == 0) ;
947 outb (0x0d, port);
948 }
949}
950
951static int ser_printk (const char *fmt, ...)
952{
953 va_list args;
954 int i;
955 long flags;
956
957 spin_lock_irqsave (&serial_lock, flags);
958 va_start (args, fmt);
959 i = vsprintf (strbuf, fmt, args);
960 ser_puts (strbuf);
961 va_end (args);
962 spin_unlock_irqrestore (&serial_lock, flags);
963
964 return i;
965}
966
967#define TRACE(a) { ser_printk a;}
968
969#else
970#define TRACE(A)
971#endif
972
973#define TRACE1(a)
974
975static void callDone (Scsi_Cmnd * SCpnt)
976{
977 if (SCpnt->result) {
978 TRACE (("*** %.08lx %.02x <%d.%d.%d> = %x\n",
979 SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel,
980 SCpnt->target, SCpnt->lun, SCpnt->result));
981 }
982 SCpnt->scsi_done (SCpnt);
983}
984
985
986
987
988
989
990
991
992
993
994
995static void mega_freeSCB (mega_host_config * megaCfg, mega_scb * pScb)
996{
997
998 mega_scb *pScbtmp;
999
1000 if ((pScb == NULL) || (pScb->idx >= 0xFE)) {
1001 return;
1002 }
1003#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1004 switch (pScb->dma_type) {
1005 case M_RD_DMA_TYPE_NONE:
1006 break;
1007 case M_RD_PTHRU_WITH_BULK_DATA:
1008 pci_unmap_single (megaCfg->dev, pScb->dma_h_bulkdata,
1009 pScb->pthru->dataxferlen,
1010 pScb->dma_direction);
1011 break;
1012 case M_RD_EPTHRU_WITH_BULK_DATA:
1013 pci_unmap_single (megaCfg->dev, pScb->dma_h_bulkdata,
1014 pScb->epthru->dataxferlen,
1015 pScb->dma_direction);
1016 break;
1017 case M_RD_PTHRU_WITH_SGLIST:
1018 {
1019 int count;
1020 for (count = 0; count < pScb->sglist_count; count++) {
1021 pci_unmap_single (megaCfg->dev,
1022 pScb->dma_h_sglist[count],
1023 pScb->sgList[count].length,
1024 pScb->dma_direction);
1025
1026 }
1027 break;
1028 }
1029 case M_RD_BULK_DATA_ONLY:
1030 pci_unmap_single (megaCfg->dev,
1031 pScb->dma_h_bulkdata,
1032 pScb->iDataSize, pScb->dma_direction);
1033
1034 break;
1035 case M_RD_SGLIST_ONLY:
1036 pci_unmap_sg (megaCfg->dev,
1037 pScb->SCpnt->request_buffer,
1038 pScb->SCpnt->use_sg, pScb->dma_direction);
1039 break;
1040 default:
1041 break;
1042 }
1043#endif
1044
1045
1046 if (pScb == megaCfg->qPendingH) {
1047
1048 if (megaCfg->qPendingH == megaCfg->qPendingT)
1049 megaCfg->qPendingH = megaCfg->qPendingT = NULL;
1050 else
1051 megaCfg->qPendingH = megaCfg->qPendingH->next;
1052
1053 megaCfg->qPcnt--;
1054
1055 } else {
1056 for (pScbtmp = megaCfg->qPendingH; pScbtmp;
1057 pScbtmp = pScbtmp->next) {
1058
1059 if (pScbtmp->next == pScb) {
1060
1061 pScbtmp->next = pScb->next;
1062
1063 if (pScb == megaCfg->qPendingT) {
1064 megaCfg->qPendingT = pScbtmp;
1065 }
1066
1067 megaCfg->qPcnt--;
1068 break;
1069 }
1070 }
1071 }
1072
1073
1074 pScb->state = SCB_FREE;
1075 pScb->SCpnt = NULL;
1076
1077 if (megaCfg->qFreeH == (mega_scb *) NULL) {
1078 megaCfg->qFreeH = megaCfg->qFreeT = pScb;
1079 } else {
1080 megaCfg->qFreeT->next = pScb;
1081 megaCfg->qFreeT = pScb;
1082 }
1083
1084 megaCfg->qFreeT->next = NULL;
1085 megaCfg->qFcnt++;
1086
1087}
1088
1089
1090
1091
1092
1093static mega_scb *mega_allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
1094{
1095 mega_scb *pScb;
1096
1097
1098 if ((pScb = megaCfg->qFreeH) != NULL) {
1099 megaCfg->qFreeH = pScb->next;
1100 megaCfg->qFcnt--;
1101
1102 pScb->isrcount = jiffies;
1103 pScb->next = NULL;
1104 pScb->state = SCB_ACTIVE;
1105 pScb->SCpnt = SCpnt;
1106
1107#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1108 pScb->dma_type = M_RD_DMA_TYPE_NONE;
1109#endif
1110
1111 return pScb;
1112 }
1113
1114 printk (KERN_WARNING "Megaraid: Could not allocate free SCB!!!\n");
1115
1116 return NULL;
1117}
1118
1119
1120static void mega_rundoneq (mega_host_config * megaCfg)
1121{
1122 Scsi_Cmnd *SCpnt;
1123
1124 while ((SCpnt = megaCfg->qCompletedH) != NULL) {
1125 megaCfg->qCompletedH = (Scsi_Cmnd *) SCpnt->host_scribble;
1126 megaCfg->qCcnt--;
1127
1128 SCpnt->host_scribble = (unsigned char *) NULL;
1129
1130 callDone (SCpnt);
1131 }
1132
1133 megaCfg->qCompletedH = megaCfg->qCompletedT = NULL;
1134}
1135
1136
1137
1138
1139
1140static int mega_runpendq (mega_host_config * megaCfg)
1141{
1142 mega_scb *pScb;
1143 int rc;
1144
1145
1146 for (pScb = megaCfg->qPendingH; pScb; pScb = pScb->next) {
1147 if (pScb->state == SCB_ACTIVE) {
1148 if ((rc =
1149 megaIssueCmd (megaCfg, pScb->mboxData, pScb, 1)) == -1)
1150 return rc;
1151 }
1152 }
1153 return 0;
1154}
1155
1156
1157
1158static void mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb, int status)
1159{
1160 int islogical;
1161 Scsi_Cmnd *SCpnt;
1162 mega_passthru *pthru;
1163 mega_ext_passthru *epthru;
1164 mega_mailbox *mbox;
1165 struct scatterlist *sgList;
1166 u8 c;
1167
1168 if (pScb == NULL) {
1169 TRACE (("NULL pScb in mega_cmd_done!"));
1170 printk(KERN_CRIT "NULL pScb in mega_cmd_done!");
1171 }
1172
1173 SCpnt = pScb->SCpnt;
1174
1175#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1176 pthru = pScb->pthru;
1177 epthru = pScb->epthru;
1178#else
1179 pthru = &pScb->pthru;
1180 epthru = &pScb->epthru;
1181#endif
1182
1183 mbox = (mega_mailbox *) & pScb->mboxData;
1184
1185 if (SCpnt == NULL) {
1186 TRACE (("NULL SCpnt in mega_cmd_done!"));
1187 TRACE (("pScb->idx = ", pScb->idx));
1188 TRACE (("pScb->state = ", pScb->state));
1189 TRACE (("pScb->state = ", pScb->state));
1190 panic(KERN_ERR "megaraid:Problem...!\n");
1191 }
1192
1193#if 0
1194 islogical = ( (SCpnt->channel >= megaCfg->productInfo.SCSIChanPresent) &&
1195 (SCpnt->channel <= megaCfg->host->max_channel) );
1196#endif
1197#if 0
1198 islogical = (SCpnt->channel == megaCfg->host->max_channel);
1199#endif
1200 islogical = megaCfg->logdrv_chan[SCpnt->channel];
1201
1202#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1203
1204 switch (SCpnt->cmnd[0]) {
1205 case INQUIRY:
1206 case READ_CAPACITY:
1207 if ( SCpnt->use_sg ) {
1208 sgList = (struct scatterlist *)SCpnt->request_buffer;
1209 memcpy(sgList[0].address, pScb->bounce_buffer,
1210 SCpnt->request_bufflen);
1211 } else {
1212 memcpy (SCpnt->request_buffer, pScb->bounce_buffer,
1213 SCpnt->request_bufflen);
1214 }
1215 break;
1216 }
1217#endif
1218
1219 mega_freeSCB (megaCfg, pScb);
1220
1221
1222
1223
1224
1225
1226#if 0
1227 if (SCpnt->cmnd[0] == INQUIRY && ((((u_char *) SCpnt->request_buffer)[0] & 0x1F) == TYPE_DISK) && !islogical) {
1228 status = 0xF0;
1229 }
1230#endif
1231 if (SCpnt->cmnd[0] == INQUIRY && !islogical) {
1232 if ( SCpnt->use_sg ) {
1233 sgList = (struct scatterlist *)SCpnt->request_buffer;
1234 memcpy(&c, sgList[0].address, 0x1);
1235 } else {
1236 memcpy(&c, SCpnt->request_buffer, 0x1);
1237 }
1238#if 0
1239 if( (c & 0x1F ) == TYPE_DISK ) {
1240 status = 0xF0;
1241 }
1242#endif
1243 if(IS_RAID_CH(megaCfg, SCpnt->channel) && ((c & 0x1F) == TYPE_DISK)) {
1244 status = 0xF0;
1245 }
1246 }
1247
1248
1249
1250 SCpnt->result = 0;
1251
1252 if ( 0 && SCpnt->cmnd[0] & M_RD_IOCTL_CMD ) {
1253 switch (status) {
1254 case 2:
1255 case 0xF0:
1256 case 0xF4:
1257 SCpnt->result = (DID_BAD_TARGET << 16) | status;
1258 break;
1259 default:
1260 SCpnt->result |= status;
1261 }
1262 } else {
1263
1264 switch (status) {
1265 case 0x00:
1266 SCpnt->result |= (DID_OK << 16);
1267 break;
1268
1269 case 0x02:
1270
1271
1272 if (mbox->cmd == MEGA_MBOXCMD_PASSTHRU || mbox->cmd ==
1273 MEGA_MBOXCMD_PASSTHRU64 ) {
1274
1275 memcpy (SCpnt->sense_buffer, pthru->reqsensearea, 14);
1276
1277 SCpnt->result = (DRIVER_SENSE << 24) | (DID_OK << 16) |
1278 (CHECK_CONDITION << 1);
1279
1280 } else if (mbox->cmd == MEGA_MBOXCMD_EXTPASSTHRU) {
1281
1282 memcpy( SCpnt->sense_buffer, epthru->reqsensearea, 14);
1283
1284 SCpnt->result = (DRIVER_SENSE << 24) | (DID_OK << 16) |
1285 (CHECK_CONDITION << 1);
1286
1287 } else {
1288 SCpnt->sense_buffer[0] = 0x70;
1289 SCpnt->sense_buffer[2] = ABORTED_COMMAND;
1290 SCpnt->result |= (CHECK_CONDITION << 1);
1291 }
1292 break;
1293
1294 case 0x08:
1295 SCpnt->result |= (DID_BUS_BUSY << 16) | status;
1296 break;
1297
1298 default:
1299 SCpnt->result |= (DID_BAD_TARGET << 16) | status;
1300 break;
1301 }
1302 }
1303
1304
1305 if (megaCfg->qCompletedH == NULL) {
1306 megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
1307 } else {
1308 megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
1309 megaCfg->qCompletedT = SCpnt;
1310 }
1311
1312 megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
1313 megaCfg->qCcnt++;
1314}
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325static mega_scb *mega_build_cmd (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
1326{
1327 mega_scb *pScb;
1328 mega_mailbox *mbox;
1329 mega_passthru *pthru;
1330 mega_ext_passthru *epthru;
1331 long seg;
1332 char islogical;
1333 int max_ldrv_num;
1334 int channel = 0;
1335 int target = 0;
1336 int ldrv_num = 0;
1337
1338 if ((SCpnt->cmnd[0] == MEGADEVIOC))
1339 return megadev_doioctl (megaCfg, SCpnt);
1340
1341 if ((SCpnt->cmnd[0] == M_RD_IOCTL_CMD)
1342 || (SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW))
1343#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
1344 return mega_ioctl (megaCfg, SCpnt);
1345#else
1346 {
1347 printk(KERN_WARNING "megaraid ioctl: older interface - "
1348 "not supported.\n");
1349 return NULL;
1350 }
1351#endif
1352
1353#if 0
1354 islogical = ( (SCpnt->channel >= megaCfg->productInfo.SCSIChanPresent) &&
1355 (SCpnt->channel <= megaCfg->host->max_channel) );
1356#endif
1357#if 0
1358 islogical = (IS_RAID_CH(SCpnt->channel) &&
1359 (SCpnt->channel == megaCfg->host->max_channel));
1360#endif
1361
1362
1363
1364
1365 islogical = megaCfg->logdrv_chan[SCpnt->channel];
1366
1367
1368
1369
1370
1371
1372
1373
1374 if( megaCfg->boot_pdrv_enabled ) {
1375 if( islogical ) {
1376
1377 channel = SCpnt->channel - megaCfg->productInfo.SCSIChanPresent;
1378 }
1379 else {
1380 channel = SCpnt->channel;
1381 target = SCpnt->target;
1382
1383
1384
1385
1386
1387
1388 if( target == 0 ) {
1389 target = megaCfg->boot_pdrv_tgt;
1390 }
1391 else if( target == megaCfg->boot_pdrv_tgt ) {
1392 target = 0;
1393 }
1394 }
1395 }
1396 else {
1397 if( islogical ) {
1398 channel = SCpnt->channel;
1399 }
1400 else {
1401 channel = SCpnt->channel - NVIRT_CHAN;
1402 target = SCpnt->target;
1403 }
1404 }
1405
1406 if ( ! megaCfg->support_ext_cdb ) {
1407 if (!islogical && SCpnt->lun != 0) {
1408 SCpnt->result = (DID_BAD_TARGET << 16);
1409 callDone (SCpnt);
1410 return NULL;
1411 }
1412 }
1413
1414 if (!islogical && SCpnt->target == skip_id) {
1415 SCpnt->result = (DID_BAD_TARGET << 16);
1416 callDone (SCpnt);
1417 return NULL;
1418 }
1419
1420 if (islogical) {
1421
1422
1423 if( SCpnt->lun != 0 ) {
1424 SCpnt->result = (DID_BAD_TARGET << 16);
1425 callDone (SCpnt);
1426 return NULL;
1427 }
1428
1429 ldrv_num = mega_get_ldrv_num(megaCfg, SCpnt, channel);
1430
1431 max_ldrv_num = (megaCfg->flag & BOARD_40LD) ?
1432 FC_MAX_LOGICAL_DRIVES : MAX_LOGICAL_DRIVES;
1433
1434
1435
1436
1437 if(megaCfg->read_ldidmap) {
1438 max_ldrv_num += 0x80;
1439 }
1440
1441 if( ldrv_num > max_ldrv_num ) {
1442 SCpnt->result = (DID_BAD_TARGET << 16);
1443 callDone (SCpnt);
1444 return NULL;
1445 }
1446
1447 } else {
1448 if ( SCpnt->lun > 7) {
1449
1450 SCpnt->result = (DID_BAD_TARGET << 16);
1451 callDone (SCpnt);
1452 return NULL;
1453 }
1454 }
1455
1456
1457
1458
1459
1460 if (islogical) {
1461 switch (SCpnt->cmnd[0]) {
1462 case TEST_UNIT_READY:
1463 memset (SCpnt->request_buffer, 0, SCpnt->request_bufflen);
1464 SCpnt->result = (DID_OK << 16);
1465 callDone (SCpnt);
1466 return NULL;
1467
1468 case MODE_SENSE:
1469 memset (SCpnt->request_buffer, 0, SCpnt->cmnd[4]);
1470 SCpnt->result = (DID_OK << 16);
1471 callDone (SCpnt);
1472 return NULL;
1473
1474 case READ_CAPACITY:
1475 case INQUIRY:
1476 if(!(megaCfg->flag & (1L << SCpnt->channel))) {
1477 printk(KERN_NOTICE
1478 "scsi%d: scanning virtual channel %d for logical drives.\n",
1479 megaCfg->host->host_no, channel);
1480
1481 megaCfg->flag |= (1L << SCpnt->channel);
1482 }
1483
1484
1485 if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
1486 SCpnt->result = (DID_ERROR << 16);
1487 callDone (SCpnt);
1488 return NULL;
1489 }
1490#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1491 pthru = pScb->pthru;
1492#else
1493 pthru = &pScb->pthru;
1494#endif
1495
1496 mbox = (mega_mailbox *) & pScb->mboxData;
1497 memset (mbox, 0, sizeof (pScb->mboxData));
1498 memset (pthru, 0, sizeof (mega_passthru));
1499 pthru->timeout = 0;
1500 pthru->ars = 1;
1501 pthru->reqsenselen = 14;
1502 pthru->islogical = 1;
1503 pthru->logdrv = ldrv_num;
1504 pthru->cdblen = SCpnt->cmd_len;
1505
1506#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1507
1508 pScb->dma_direction = PCI_DMA_BIDIRECTIONAL;
1509 pScb->dma_type = M_RD_PTHRU_WITH_BULK_DATA;
1510
1511#if 0
1512
1513 pScb->dma_h_bulkdata
1514 = pci_map_single (megaCfg->dev,
1515 SCpnt->request_buffer,
1516 SCpnt->request_bufflen,
1517 pScb->dma_direction);
1518
1519 pthru->dataxferaddr = pScb->dma_h_bulkdata;
1520#else
1521
1522 pthru->dataxferaddr = pScb->dma_bounce_buffer;
1523 pScb->dma_type = M_RD_DMA_TYPE_NONE;
1524#endif
1525
1526#else
1527 pthru->dataxferaddr =
1528 virt_to_bus (SCpnt->request_buffer);
1529#endif
1530
1531 pthru->dataxferlen = SCpnt->request_bufflen;
1532 memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len);
1533
1534
1535 mbox->cmd = MEGA_MBOXCMD_PASSTHRU;
1536
1537#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1538 mbox->xferaddr = pScb->dma_passthruhandle64;
1539 TRACE1 (("M_RD_PTHRU_WITH_BULK_DATA Enabled \n"));
1540#else
1541 mbox->xferaddr = virt_to_bus (pthru);
1542#endif
1543 return pScb;
1544
1545 case READ_6:
1546 case WRITE_6:
1547 case READ_10:
1548 case WRITE_10:
1549
1550 if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
1551 SCpnt->result = (DID_ERROR << 16);
1552 callDone (SCpnt);
1553 return NULL;
1554 }
1555 mbox = (mega_mailbox *) & pScb->mboxData;
1556
1557 memset (mbox, 0, sizeof (pScb->mboxData));
1558 mbox->logdrv = ldrv_num;
1559
1560 if (megaCfg->flag & BOARD_64BIT) {
1561 mbox->cmd = (*SCpnt->cmnd == READ_6
1562 || *SCpnt->cmnd ==
1563 READ_10) ? MEGA_MBOXCMD_LREAD64 :
1564 MEGA_MBOXCMD_LWRITE64;
1565 } else {
1566 mbox->cmd = (*SCpnt->cmnd == READ_6
1567 || *SCpnt->cmnd ==
1568 READ_10) ? MEGA_MBOXCMD_LREAD :
1569 MEGA_MBOXCMD_LWRITE;
1570 }
1571
1572
1573 if (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == WRITE_6) {
1574 mbox->numsectors = (u32) SCpnt->cmnd[4];
1575 mbox->lba =
1576 ((u32) SCpnt->cmnd[1] << 16) |
1577 ((u32) SCpnt->cmnd[2] << 8) |
1578 (u32) SCpnt->cmnd[3];
1579 mbox->lba &= 0x1FFFFF;
1580
1581 if (*SCpnt->cmnd == READ_6) {
1582 megaCfg->nReads[(int)ldrv_num]++;
1583 megaCfg->nReadBlocks[(int)ldrv_num] +=
1584 mbox->numsectors;
1585 } else {
1586 megaCfg->nWrites[(int)ldrv_num]++;
1587 megaCfg->nWriteBlocks[(int)ldrv_num] +=
1588 mbox->numsectors;
1589 }
1590 }
1591
1592
1593 if (*SCpnt->cmnd == READ_10 || *SCpnt->cmnd == WRITE_10) {
1594 mbox->numsectors =
1595 (u32) SCpnt->cmnd[8] |
1596 ((u32) SCpnt->cmnd[7] << 8);
1597 mbox->lba =
1598 ((u32) SCpnt->cmnd[2] << 24) |
1599 ((u32) SCpnt->cmnd[3] << 16) |
1600 ((u32) SCpnt->cmnd[4] << 8) |
1601 (u32) SCpnt->cmnd[5];
1602
1603 if (*SCpnt->cmnd == READ_10) {
1604 megaCfg->nReads[(int)ldrv_num]++;
1605 megaCfg->nReadBlocks[(int)ldrv_num] +=
1606 mbox->numsectors;
1607 } else {
1608 megaCfg->nWrites[(int)ldrv_num]++;
1609 megaCfg->nWriteBlocks[(int)ldrv_num] +=
1610 mbox->numsectors;
1611 }
1612 }
1613
1614
1615 if (*SCpnt->cmnd == READ_12 || *SCpnt->cmnd == WRITE_12) {
1616 mbox->lba =
1617 ((u32) SCpnt->cmnd[2] << 24) |
1618 ((u32) SCpnt->cmnd[3] << 16) |
1619 ((u32) SCpnt->cmnd[4] << 8) |
1620 (u32) SCpnt->cmnd[5];
1621
1622 mbox->numsectors =
1623 ((u32) SCpnt->cmnd[6] << 24) |
1624 ((u32) SCpnt->cmnd[7] << 16) |
1625 ((u32) SCpnt->cmnd[8] << 8) |
1626 (u32) SCpnt->cmnd[9];
1627
1628 if (*SCpnt->cmnd == READ_12) {
1629 megaCfg->nReads[(int)ldrv_num]++;
1630 megaCfg->nReadBlocks[(int)ldrv_num] +=
1631 mbox->numsectors;
1632 } else {
1633 megaCfg->nWrites[(int)ldrv_num]++;
1634 megaCfg->nWriteBlocks[(int)ldrv_num] +=
1635 mbox->numsectors;
1636 }
1637 }
1638
1639#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1640 if (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == READ_10
1641 || *SCpnt->cmnd == READ_12) {
1642 pScb->dma_direction = PCI_DMA_FROMDEVICE;
1643 } else {
1644 pScb->dma_direction = PCI_DMA_TODEVICE;
1645 }
1646#endif
1647
1648
1649 mbox->numsgelements = mega_build_sglist (megaCfg, pScb,
1650 (u32 *)&mbox->xferaddr, (u32 *)&seg);
1651
1652#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1653 pScb->iDataSize = seg;
1654
1655 if (mbox->numsgelements) {
1656 pScb->dma_type = M_RD_SGLIST_ONLY;
1657 TRACE1 (("M_RD_SGLIST_ONLY Enabled \n"));
1658 } else {
1659 pScb->dma_type = M_RD_BULK_DATA_ONLY;
1660 TRACE1 (("M_RD_BULK_DATA_ONLY Enabled \n"));
1661 }
1662#endif
1663
1664 return pScb;
1665 default:
1666 SCpnt->result = (DID_BAD_TARGET << 16);
1667 callDone (SCpnt);
1668 return NULL;
1669 }
1670 }
1671
1672
1673
1674
1675
1676 else {
1677
1678 if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
1679 SCpnt->result = (DID_ERROR << 16);
1680 callDone (SCpnt);
1681 return NULL;
1682 }
1683
1684 mbox = (mega_mailbox *) pScb->mboxData;
1685 memset (mbox, 0, sizeof (pScb->mboxData));
1686
1687 if ( megaCfg->support_ext_cdb && SCpnt->cmd_len > 10 ) {
1688 epthru = mega_prepare_extpassthru(megaCfg, pScb, SCpnt, channel,
1689 target);
1690 mbox->cmd = MEGA_MBOXCMD_EXTPASSTHRU;
1691#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1692 mbox->xferaddr = pScb->dma_ext_passthruhandle64;
1693
1694 if(epthru->numsgelements) {
1695 pScb->dma_type = M_RD_PTHRU_WITH_SGLIST;
1696 } else {
1697 pScb->dma_type = M_RD_EPTHRU_WITH_BULK_DATA;
1698 }
1699#else
1700 mbox->xferaddr = virt_to_bus(epthru);
1701#endif
1702 }
1703 else {
1704 pthru = mega_prepare_passthru(megaCfg, pScb, SCpnt, channel,
1705 target);
1706
1707
1708 mbox->cmd = MEGA_MBOXCMD_PASSTHRU;
1709#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1710 mbox->xferaddr = pScb->dma_passthruhandle64;
1711
1712 if (pthru->numsgelements) {
1713 pScb->dma_type = M_RD_PTHRU_WITH_SGLIST;
1714 } else {
1715 pScb->dma_type = M_RD_PTHRU_WITH_BULK_DATA;
1716 }
1717#else
1718 mbox->xferaddr = virt_to_bus(pthru);
1719#endif
1720 }
1721 return pScb;
1722 }
1723 return NULL;
1724}
1725
1726static int
1727mega_get_ldrv_num(mega_host_config *this_hba, Scsi_Cmnd *sc, int channel)
1728{
1729 int tgt;
1730 int ldrv_num;
1731
1732 tgt = sc->target;
1733
1734 if ( tgt > 7 ) tgt--;
1735
1736 ldrv_num = (channel * 15) + tgt;
1737
1738
1739
1740
1741 if( this_hba->boot_ldrv_enabled ) {
1742 if( ldrv_num == 0 ) {
1743 ldrv_num = this_hba->boot_ldrv;
1744 }
1745 else {
1746 if( ldrv_num <= this_hba->boot_ldrv ) {
1747 ldrv_num--;
1748 }
1749 }
1750 }
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762 if( this_hba->support_random_del && this_hba->read_ldidmap ) {
1763 switch(sc->cmnd[0]) {
1764 case READ_6:
1765 case WRITE_6:
1766 case READ_10:
1767 case WRITE_10:
1768 ldrv_num += 0x80;
1769 }
1770 }
1771
1772 return ldrv_num;
1773}
1774
1775
1776static mega_passthru *
1777mega_prepare_passthru(mega_host_config *megacfg, mega_scb *scb, Scsi_Cmnd *sc,
1778 int channel, int target)
1779{
1780 mega_passthru *pthru;
1781
1782#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1783 pthru = scb->pthru;
1784#else
1785 pthru = &scb->pthru;
1786#endif
1787 memset (pthru, 0, sizeof (mega_passthru));
1788
1789
1790
1791 pthru->timeout = 2;
1792 pthru->ars = 1;
1793 pthru->reqsenselen = 14;
1794 pthru->islogical = 0;
1795 pthru->channel = (megacfg->flag & BOARD_40LD) ? 0 : channel;
1796 pthru->target = (megacfg->flag & BOARD_40LD) ?
1797 (channel << 4) | target : target;
1798 pthru->cdblen = sc->cmd_len;
1799 pthru->logdrv = sc->lun;
1800
1801 memcpy (pthru->cdb, sc->cmnd, sc->cmd_len);
1802
1803#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1804
1805 scb->dma_direction = PCI_DMA_BIDIRECTIONAL;
1806
1807
1808 switch (sc->cmnd[0]) {
1809 case INQUIRY:
1810 case READ_CAPACITY:
1811
1812 if(!(megacfg->flag & (1L << sc->channel))) {
1813 printk(KERN_NOTICE
1814 "scsi%d: scanning physical channel %d for devices.\n",
1815 megacfg->host->host_no, channel);
1816
1817 megacfg->flag |= (1L << sc->channel);
1818 }
1819
1820 pthru->numsgelements = 0;
1821 pthru->dataxferaddr = scb->dma_bounce_buffer;
1822 pthru->dataxferlen = sc->request_bufflen;
1823 break;
1824 default:
1825 pthru->numsgelements =
1826 mega_build_sglist(
1827 megacfg, scb, (u32 *)&pthru->dataxferaddr,
1828 (u32 *)&pthru->dataxferlen
1829 );
1830 break;
1831 }
1832#else
1833 pthru->numsgelements =
1834 mega_build_sglist(
1835 megacfg, scb, (u32 *)&pthru->dataxferaddr,
1836 (u32 *)&pthru->dataxferlen
1837 );
1838#endif
1839 return pthru;
1840}
1841
1842static mega_ext_passthru *
1843mega_prepare_extpassthru(mega_host_config *megacfg, mega_scb *scb,
1844 Scsi_Cmnd *sc, int channel, int target)
1845{
1846 mega_ext_passthru *epthru;
1847
1848#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1849 epthru = scb->epthru;
1850#else
1851 epthru = &scb->epthru;
1852#endif
1853 memset(epthru, 0, sizeof(mega_ext_passthru));
1854
1855
1856
1857 epthru->timeout = 2;
1858 epthru->ars = 1;
1859 epthru->reqsenselen = 14;
1860 epthru->islogical = 0;
1861 epthru->channel = (megacfg->flag & BOARD_40LD) ? 0 : channel;
1862 epthru->target = (megacfg->flag & BOARD_40LD) ?
1863 (channel << 4) | target : target;
1864 epthru->cdblen = sc->cmd_len;
1865 epthru->logdrv = sc->lun;
1866
1867 memcpy(epthru->cdb, sc->cmnd, sc->cmd_len);
1868
1869#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1870
1871 scb->dma_direction = PCI_DMA_BIDIRECTIONAL;
1872
1873
1874 switch (sc->cmnd[0]) {
1875 case INQUIRY:
1876 case READ_CAPACITY:
1877 if(!(megacfg->flag & (1L << sc->channel))) {
1878 printk(KERN_NOTICE
1879 "scsi%d: scanning physical channel %d for devices.\n",
1880 megacfg->host->host_no, channel);
1881
1882 megacfg->flag |= (1L << sc->channel);
1883 }
1884
1885 epthru->numsgelements = 0;
1886 epthru->dataxferaddr = scb->dma_bounce_buffer;
1887 epthru->dataxferlen = sc->request_bufflen;
1888 break;
1889 default:
1890 epthru->numsgelements =
1891 mega_build_sglist(
1892 megacfg, scb, (u32 *)&epthru->dataxferaddr,
1893 (u32 *)&epthru->dataxferlen
1894 );
1895 break;
1896 }
1897#else
1898 epthru->numsgelements =
1899 mega_build_sglist(
1900 megacfg, scb, (u32 *)&epthru->dataxferaddr,
1901 (u32 *)&epthru->dataxferlen
1902 );
1903#endif
1904 return epthru;
1905}
1906
1907
1908
1909
1910
1911
1912static int mega_driver_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
1913{
1914 unsigned char *data = (unsigned char *) SCpnt->request_buffer;
1915 mega_driver_info driver_info;
1916
1917
1918 if (SCpnt->cmnd[0] != M_RD_DRIVER_IOCTL_INTERFACE)
1919 return 0;
1920
1921 switch (SCpnt->cmnd[1]) {
1922 case GET_DRIVER_INFO:
1923 if (SCpnt->request_bufflen < sizeof (driver_info)) {
1924 SCpnt->result = DID_BAD_TARGET << 16;
1925 callDone (SCpnt);
1926 return 1;
1927 }
1928
1929 driver_info.size = sizeof (driver_info) - sizeof (int);
1930 driver_info.version = MEGARAID_IOCTL_VERSION;
1931 memcpy (data, &driver_info, sizeof (driver_info));
1932 break;
1933 default:
1934 SCpnt->result = DID_BAD_TARGET << 16;
1935 }
1936
1937 callDone (SCpnt);
1938 return 1;
1939}
1940
1941static void inline set_mbox_xfer_addr (mega_host_config * megaCfg, mega_scb * pScb,
1942 mega_ioctl_mbox * mbox, u32 direction)
1943{
1944
1945#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1946 switch (direction) {
1947 case TO_DEVICE:
1948 pScb->dma_direction = PCI_DMA_TODEVICE;
1949 break;
1950 case FROM_DEVICE:
1951 pScb->dma_direction = PCI_DMA_FROMDEVICE;
1952 break;
1953 case FROMTO_DEVICE:
1954 pScb->dma_direction = PCI_DMA_BIDIRECTIONAL;
1955 break;
1956 }
1957
1958 pScb->dma_h_bulkdata
1959 = pci_map_single (megaCfg->dev,
1960 pScb->buff_ptr,
1961 pScb->iDataSize, pScb->dma_direction);
1962 mbox->xferaddr = pScb->dma_h_bulkdata;
1963 pScb->dma_type = M_RD_BULK_DATA_ONLY;
1964 TRACE1 (("M_RD_BULK_DATA_ONLY Enabled \n"));
1965#else
1966 mbox->xferaddr = virt_to_bus (pScb->buff_ptr);
1967#endif
1968}
1969
1970#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
1971
1972
1973
1974
1975static mega_scb *mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
1976{
1977 mega_scb *pScb;
1978 mega_ioctl_mbox *mbox;
1979 mega_mailbox *mailbox;
1980 mega_passthru *pthru;
1981 u8 *mboxdata;
1982 long seg, i = 0;
1983 unsigned char *data = (unsigned char *) SCpnt->request_buffer;
1984
1985 if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
1986 SCpnt->result = (DID_ERROR << 16);
1987 callDone (SCpnt);
1988 return NULL;
1989 }
1990 pthru = &pScb->pthru;
1991
1992 mboxdata = (u8 *) & pScb->mboxData;
1993 mbox = (mega_ioctl_mbox *) & pScb->mboxData;
1994 mailbox = (mega_mailbox *) & pScb->mboxData;
1995 memset (mailbox, 0, sizeof (pScb->mboxData));
1996
1997 if (data[0] == 0x03) {
1998 unsigned char cdblen = data[2];
1999 memset (pthru, 0, sizeof (mega_passthru));
2000 pthru->islogical = (data[cdblen + 3] & 0x80) ? 1 : 0;
2001 pthru->timeout = data[cdblen + 3] & 0x07;
2002 pthru->reqsenselen = 14;
2003 pthru->ars = (data[cdblen + 3] & 0x08) ? 1 : 0;
2004 pthru->logdrv = data[cdblen + 4];
2005 pthru->channel = data[cdblen + 5];
2006 pthru->target = data[cdblen + 6];
2007 pthru->cdblen = cdblen;
2008 memcpy (pthru->cdb, &data[3], cdblen);
2009
2010 mailbox->cmd = MEGA_MBOXCMD_PASSTHRU;
2011
2012
2013 pthru->numsgelements = mega_build_sglist (megaCfg, pScb,
2014 (u32 *) & pthru->
2015 dataxferaddr,
2016 (u32 *) & pthru->
2017 dataxferlen);
2018
2019 mailbox->xferaddr = virt_to_bus (pthru);
2020
2021 for (i = 0; i < (SCpnt->request_bufflen - cdblen - 7); i++) {
2022 data[i] = data[i + cdblen + 7];
2023 }
2024 return pScb;
2025 }
2026
2027
2028#if LINUX_VERSION_CODE > KERNEL_VERSION(2,0,24)
2029
2030
2031
2032
2033
2034
2035
2036 if (SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW) {
2037
2038
2039
2040
2041
2042 char *user_area = (char *)*((u32*)&SCpnt->cmnd[4]);
2043 u32 xfer_size = *((u32 *) & SCpnt->cmnd[8]);
2044 switch (data[0]) {
2045 case FW_FIRE_WRITE:
2046 case FW_FIRE_FLASH:
2047 if ((ulong) user_area & (PAGE_SIZE - 1)) {
2048 printk
2049 ("megaraid:user address not aligned on 4K boundary.Error.\n");
2050 SCpnt->result = (DID_ERROR << 16);
2051 callDone (SCpnt);
2052 return NULL;
2053 }
2054 break;
2055 default:
2056 break;
2057 }
2058
2059 if (!(pScb->buff_ptr = kmalloc (xfer_size, GFP_KERNEL))) {
2060 printk
2061 ("megaraid: Insufficient mem for M_RD_IOCTL_CMD_NEW.\n");
2062 SCpnt->result = (DID_ERROR << 16);
2063 callDone (SCpnt);
2064 return NULL;
2065 }
2066
2067 copy_from_user (pScb->buff_ptr, user_area, xfer_size);
2068 pScb->iDataSize = xfer_size;
2069
2070 switch (data[0]) {
2071 case DCMD_FC_CMD:
2072 switch (data[1]) {
2073 case DCMD_FC_READ_NVRAM_CONFIG:
2074 case DCMD_GET_DISK_CONFIG:
2075 {
2076 if ((ulong) pScb->
2077 buff_ptr & (PAGE_SIZE - 1)) {
2078 printk
2079 ("megaraid:user address not sufficient Error.\n");
2080 SCpnt->result =
2081 (DID_ERROR << 16);
2082 callDone (SCpnt);
2083 return NULL;
2084 }
2085
2086
2087 mega_build_kernel_sg (pScb->buff_ptr,
2088 xfer_size,
2089 pScb, mbox);
2090 break;
2091 }
2092 default:
2093 break;
2094 }
2095 break;
2096 }
2097
2098 }
2099#endif
2100
2101 mbox->cmd = data[0];
2102 mbox->channel = data[1];
2103 mbox->param = data[2];
2104 mbox->pad[0] = data[3];
2105 mbox->logdrv = data[4];
2106
2107 if (SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW) {
2108 switch (data[0]) {
2109 case FW_FIRE_WRITE:
2110 mbox->cmd = FW_FIRE_WRITE;
2111 mbox->channel = data[1];
2112 set_mbox_xfer_addr (megaCfg, pScb, mbox, TO_DEVICE);
2113 mbox->numsgelements = 0;
2114 break;
2115 case FW_FIRE_FLASH:
2116 mbox->cmd = FW_FIRE_FLASH;
2117 mbox->channel = data[1] | 0x80;
2118 set_mbox_xfer_addr (megaCfg, pScb, mbox, TO_DEVICE);
2119 mbox->numsgelements = 0;
2120 break;
2121 case DCMD_FC_CMD:
2122 *(mboxdata + 0) = data[0];
2123 *(mboxdata + 2) = data[1];
2124 switch (data[1]) {
2125 case DCMD_FC_READ_NVRAM_CONFIG:
2126 case DCMD_FC_READ_NVRAM_CONFIG_64:
2127
2128 *(mboxdata + 3) = mbox->numsgelements;
2129 if (megaCfg->flag & BOARD_64BIT)
2130 *(mboxdata + 2) =
2131 DCMD_FC_READ_NVRAM_CONFIG_64;
2132 break;
2133 case DCMD_WRITE_CONFIG:
2134 case DCMD_WRITE_CONFIG_64:
2135 if (megaCfg->flag & BOARD_64BIT)
2136 *(mboxdata + 2) = DCMD_WRITE_CONFIG_64;
2137 set_mbox_xfer_addr (megaCfg, pScb, mbox,
2138 TO_DEVICE);
2139 mbox->numsgelements = 0;
2140 break;
2141 case DCMD_GET_DISK_CONFIG:
2142 case DCMD_GET_DISK_CONFIG_64:
2143 if (megaCfg->flag & BOARD_64BIT)
2144 *(mboxdata + 2) =
2145 DCMD_GET_DISK_CONFIG_64;
2146 *(mboxdata + 3) = data[2];
2147
2148 *(mboxdata + 4) = mbox->numsgelements;
2149 break;
2150 case DCMD_DELETE_LOGDRV:
2151 case DCMD_DELETE_DRIVEGROUP:
2152 case NC_SUBOP_ENQUIRY3:
2153 *(mboxdata + 3) = data[2];
2154 set_mbox_xfer_addr (megaCfg, pScb, mbox,
2155 FROMTO_DEVICE);
2156 mbox->numsgelements = 0;
2157 break;
2158 case DCMD_CHANGE_LDNO:
2159 case DCMD_CHANGE_LOOPID:
2160 *(mboxdata + 3) = data[2];
2161 *(mboxdata + 4) = data[3];
2162 set_mbox_xfer_addr (megaCfg, pScb, mbox,
2163 TO_DEVICE);
2164 mbox->numsgelements = 0;
2165 break;
2166 default:
2167 set_mbox_xfer_addr (megaCfg, pScb, mbox,
2168 FROMTO_DEVICE);
2169 mbox->numsgelements = 0;
2170 break;
2171 }
2172 break;
2173 default:
2174 set_mbox_xfer_addr (megaCfg, pScb, mbox, FROMTO_DEVICE);
2175 mbox->numsgelements = 0;
2176 break;
2177 }
2178 } else {
2179
2180 mbox->numsgelements = mega_build_sglist (megaCfg, pScb,
2181 (u32 *) & mbox->
2182 xferaddr,
2183 (u32 *) & seg);
2184
2185
2186 switch (data[0]) {
2187 case 6:
2188 mbox->xferaddr = *((u32 *) & data[i + 6]);
2189 break;
2190 default:
2191 break;
2192 }
2193
2194 for (i = 0; i < (SCpnt->request_bufflen - 6); i++) {
2195 data[i] = data[i + 6];
2196 }
2197 }
2198
2199 return (pScb);
2200}
2201
2202
2203static void mega_build_kernel_sg (char *barea, ulong xfersize, mega_scb * pScb, mega_ioctl_mbox * mbox)
2204{
2205 ulong i, buffer_area, len, end, end_page, x, idx = 0;
2206
2207 buffer_area = (ulong) barea;
2208 i = buffer_area;
2209 end = buffer_area + xfersize;
2210 end_page = (end) & ~(PAGE_SIZE - 1);
2211
2212 do {
2213 len = PAGE_SIZE - (i % PAGE_SIZE);
2214 x = pScb->sgList[idx].address =
2215 virt_to_bus ((volatile void *) i);
2216 pScb->sgList[idx].length = len;
2217 i += len;
2218 idx++;
2219 } while (i < end_page);
2220
2221 if ((end - i) < 0) {
2222 printk ("megaraid:Error in user address\n");
2223 }
2224
2225 if (end - i) {
2226 pScb->sgList[idx].address = virt_to_bus ((volatile void *) i);
2227 pScb->sgList[idx].length = end - i;
2228 idx++;
2229 }
2230 mbox->xferaddr = virt_to_bus (pScb->sgList);
2231 mbox->numsgelements = idx;
2232}
2233#endif
2234
2235
2236#if DEBUG
2237static unsigned int cum_time = 0;
2238static unsigned int cum_time_cnt = 0;
2239
2240static void showMbox (mega_scb * pScb)
2241{
2242 mega_mailbox *mbox;
2243
2244 if (pScb == NULL)
2245 return;
2246
2247 mbox = (mega_mailbox *) pScb->mboxData;
2248 printk ("%u cmd:%x id:%x #scts:%x lba:%x addr:%x logdrv:%x #sg:%x\n",
2249 pScb->SCpnt->pid,
2250 mbox->cmd, mbox->cmdid, mbox->numsectors,
2251 mbox->lba, mbox->xferaddr, mbox->logdrv, mbox->numsgelements);
2252}
2253
2254#endif
2255
2256
2257
2258
2259static void megaraid_isr (int irq, void *devp, struct pt_regs *regs)
2260{
2261 IO_LOCK_T;
2262 mega_host_config * megaCfg;
2263 u_char byte, idx, sIdx, tmpBox[MAILBOX_SIZE];
2264 u32 dword = 0;
2265 mega_mailbox *mbox;
2266 mega_scb *pScb;
2267 u_char qCnt, qStatus;
2268 u_char completed[MAX_FIRMWARE_STATUS];
2269 Scsi_Cmnd *SCpnt;
2270
2271 megaCfg = (mega_host_config *) devp;
2272 mbox = (mega_mailbox *) tmpBox;
2273
2274 IO_LOCK;
2275
2276
2277 if (megaCfg->flag & BOARD_QUARTZ) {
2278 dword = RDOUTDOOR (megaCfg);
2279 if (dword != 0x10001234) {
2280
2281 IO_UNLOCK;
2282 return;
2283 }
2284 WROUTDOOR (megaCfg, 0x10001234);
2285 } else {
2286 byte = READ_PORT (megaCfg->host->io_port, INTR_PORT);
2287 if ((byte & VALID_INTR_BYTE) == 0) {
2288
2289 IO_UNLOCK;
2290 return;
2291 }
2292 WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
2293 }
2294
2295 for (idx = 0; idx < MAX_FIRMWARE_STATUS; idx++)
2296 completed[idx] = 0;
2297
2298
2299 megaCfg->nInterrupts++;
2300 while ((qCnt = megaCfg->mbox->numstatus) == 0xFF) ;
2301 megaCfg->mbox->numstatus = 0xFF;
2302
2303
2304 for (idx = 0; idx < qCnt; idx++) {
2305 while ((completed[idx] = megaCfg->mbox->completed[idx]) == 0xFF);
2306 megaCfg->mbox->completed[idx] = 0xFF;
2307 }
2308
2309 qStatus = megaCfg->mbox->status;
2310
2311 if (megaCfg->flag & BOARD_QUARTZ) {
2312
2313 WRINDOOR (megaCfg, 0x2);
2314 while (RDINDOOR (megaCfg) & 0x02) ;
2315 } else {
2316 CLEAR_INTR (megaCfg->host->io_port);
2317 }
2318
2319 for (idx = 0; idx < qCnt; idx++) {
2320 sIdx = completed[idx];
2321 if ((sIdx > 0) && (sIdx <= MAX_COMMANDS)) {
2322 pScb = &megaCfg->scbList[sIdx - 1];
2323
2324
2325
2326#if DEBUG
2327 if (((jiffies) - pScb->isrcount) > maxCmdTime) {
2328 maxCmdTime = (jiffies) - pScb->isrcount;
2329 printk
2330 ("megaraid_isr : cmd time = %u\n",
2331 maxCmdTime);
2332 }
2333#endif
2334
2335
2336
2337
2338
2339 if (pScb->state == SCB_ABORTED) {
2340 SCpnt = pScb->SCpnt;
2341 }
2342 if (pScb->state == SCB_RESET) {
2343 SCpnt = pScb->SCpnt;
2344 mega_freeSCB (megaCfg, pScb);
2345 SCpnt->result = (DID_RESET << 16);
2346 if (megaCfg->qCompletedH == NULL) {
2347 megaCfg->qCompletedH =
2348 megaCfg->qCompletedT =
2349 SCpnt;
2350 } else {
2351 megaCfg->qCompletedT->
2352 host_scribble =
2353 (unsigned char *) SCpnt;
2354 megaCfg->qCompletedT = SCpnt;
2355 }
2356 megaCfg->qCompletedT->host_scribble =
2357 (unsigned char *) NULL;
2358 megaCfg->qCcnt++;
2359 continue;
2360 }
2361
2362
2363
2364
2365
2366 if (pScb->SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW) {
2367
2368 pScb->SCpnt->result = qStatus;
2369 up (&pScb->ioctl_sem);
2370 } else {
2371
2372 mega_cmd_done (megaCfg, pScb, qStatus);
2373 }
2374 } else {
2375 printk
2376 ("megaraid: wrong cmd id completed from firmware:id=%x\n",
2377 sIdx);
2378 }
2379 }
2380
2381 mega_rundoneq (megaCfg);
2382
2383 megaCfg->flag &= ~IN_ISR;
2384
2385 mega_runpendq (megaCfg);
2386 IO_UNLOCK;
2387
2388}
2389
2390
2391
2392
2393
2394static inline int mega_busyWaitMbox (mega_host_config * megaCfg)
2395{
2396 mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;
2397 long counter;
2398
2399 for (counter = 0; counter < 10; counter++) {
2400 if (!mbox->busy) {
2401 return 0;
2402 }
2403 udelay (1);
2404 }
2405 return -1;
2406}
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423static int megaIssueCmd (mega_host_config * megaCfg, u_char * mboxData,
2424 mega_scb * pScb, int intr)
2425{
2426 volatile mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;
2427
2428#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2429 volatile mega_mailbox64 *mbox64 = (mega_mailbox64 *) megaCfg->mbox64;
2430#endif
2431
2432 u_char byte;
2433
2434#if BITS_PER_LONG==64
2435 u64 phys_mbox;
2436#else
2437 u32 phys_mbox;
2438#endif
2439 u8 retval = -1;
2440 int i;
2441
2442 mboxData[0x1] = (pScb ? pScb->idx + 1 : 0xFE);
2443 mboxData[0xF] = 1;
2444
2445#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2446
2447 phys_mbox = megaCfg->adjdmahandle64;
2448#else
2449 phys_mbox = virt_to_bus (megaCfg->mbox);
2450#endif
2451
2452
2453 if (mega_busyWaitMbox (megaCfg)) {
2454 return -1;
2455 }
2456
2457 pLastScb = pScb;
2458
2459
2460 megaCfg->mbox64->xferSegment_lo = 0;
2461 megaCfg->mbox64->xferSegment_hi = 0;
2462
2463 memcpy ((char *) mbox, mboxData, 16);
2464
2465#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2466 switch (mboxData[0]) {
2467 case MEGA_MBOXCMD_LREAD64:
2468 case MEGA_MBOXCMD_LWRITE64:
2469 mbox64->xferSegment_lo = mbox->xferaddr;
2470 mbox64->xferSegment_hi = 0;
2471 mbox->xferaddr = 0xFFFFFFFF;
2472 break;
2473 }
2474#endif
2475
2476
2477 if (intr) {
2478
2479 if (megaCfg->flag & BOARD_QUARTZ) {
2480 mbox->mraid_poll = 0;
2481 mbox->mraid_ack = 0;
2482
2483 WRINDOOR (megaCfg, phys_mbox | 0x1);
2484 } else {
2485 ENABLE_INTR (megaCfg->host->io_port);
2486 ISSUE_COMMAND (megaCfg->host->io_port);
2487 }
2488 pScb->state = SCB_ISSUED;
2489
2490 retval = 0;
2491 } else {
2492 disable_irq (megaCfg->host->irq);
2493 if (megaCfg->flag & BOARD_QUARTZ) {
2494 mbox->mraid_poll = 0;
2495 mbox->mraid_ack = 0;
2496 mbox->numstatus = 0xFF;
2497 mbox->status = 0xFF;
2498 WRINDOOR (megaCfg, phys_mbox | 0x1);
2499
2500 while (mbox->numstatus == 0xFF) ;
2501 while (mbox->mraid_poll != 0x77) ;
2502 mbox->mraid_poll = 0;
2503 mbox->mraid_ack = 0x77;
2504 mbox->numstatus = 0xFF;
2505
2506 if (pScb) {
2507 mega_cmd_done (megaCfg, pScb, mbox->status);
2508 }
2509
2510 WRINDOOR (megaCfg, phys_mbox | 0x2);
2511 while (RDINDOOR (megaCfg) & 0x2) ;
2512
2513 } else {
2514 DISABLE_INTR (megaCfg->host->io_port);
2515 ISSUE_COMMAND (megaCfg->host->io_port);
2516
2517 while (!
2518 ((byte =
2519 READ_PORT (megaCfg->host->io_port,
2520 INTR_PORT)) & INTR_VALID)) ;
2521 WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
2522
2523 ENABLE_INTR (megaCfg->host->io_port);
2524 CLEAR_INTR (megaCfg->host->io_port);
2525
2526 if (pScb) {
2527 mega_cmd_done (megaCfg, pScb, mbox->status);
2528 } else {
2529 TRACE (("Error: NULL pScb!\n"));
2530 }
2531 }
2532
2533 for (i = 0; i < MAX_FIRMWARE_STATUS; i++) {
2534 mbox->completed[i] = 0xFF;
2535 }
2536
2537 enable_irq (megaCfg->host->irq);
2538 retval = mbox->status;
2539 }
2540
2541 return retval;
2542}
2543
2544
2545
2546
2547
2548
2549
2550
2551static int
2552mega_build_sglist (mega_host_config * megaCfg, mega_scb * scb,
2553 u32 * buffer, u32 * length)
2554{
2555 struct scatterlist *sgList;
2556 int idx;
2557
2558#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2559 int sgcnt;
2560#endif
2561
2562 mega_mailbox *mbox = NULL;
2563
2564 mbox = (mega_mailbox *) scb->mboxData;
2565
2566 if (scb->SCpnt->use_sg == 0) {
2567
2568#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2569 scb->dma_h_bulkdata = pci_map_single (megaCfg->dev,
2570 scb->SCpnt->request_buffer,
2571 scb->SCpnt->request_bufflen,
2572 scb->dma_direction);
2573
2574
2575
2576 if ((megaCfg->flag & BOARD_64BIT) &&
2577 ((mbox->cmd == MEGA_MBOXCMD_LREAD64) ||
2578 (mbox->cmd == MEGA_MBOXCMD_LWRITE64))) {
2579 scb->sg64List[0].address = scb->dma_h_bulkdata;
2580 scb->sg64List[0].length = scb->SCpnt->request_bufflen;
2581 *buffer = scb->dma_sghandle64;
2582 *length = (u32)scb->SCpnt->request_bufflen;
2583 scb->sglist_count = 1;
2584 return 1;
2585 } else {
2586 *buffer = scb->dma_h_bulkdata;
2587 *length = (u32) scb->SCpnt->request_bufflen;
2588 }
2589#else
2590 *buffer = virt_to_bus (scb->SCpnt->request_buffer);
2591 *length = (u32) scb->SCpnt->request_bufflen;
2592#endif
2593 return 0;
2594 }
2595
2596 sgList = (struct scatterlist *) scb->SCpnt->request_buffer;
2597#if 0
2598 if (scb->SCpnt->use_sg == 1) {
2599
2600#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2601 scb->dma_h_bulkdata = pci_map_single (megaCfg->dev,
2602 sgList[0].address,
2603 sgList[0].length, scb->dma_direction);
2604
2605 if ((megaCfg->flag & BOARD_64BIT) &&
2606 ((mbox->cmd == MEGA_MBOXCMD_LREAD64) ||
2607 (mbox->cmd == MEGA_MBOXCMD_LWRITE64))) {
2608 scb->sg64List[0].address = scb->dma_h_bulkdata;
2609 scb->sg64List[0].length = scb->SCpnt->request_bufflen;
2610 *buffer = scb->dma_sghandle64;
2611 *length = 0;
2612 scb->sglist_count = 1;
2613 return 1;
2614 } else {
2615 *buffer = scb->dma_h_bulkdata;
2616 *length = (u32) sgList[0].length;
2617 }
2618#else
2619 *buffer = virt_to_bus (sgList[0].address);
2620 *length = (u32) sgList[0].length;
2621#endif
2622
2623 return 0;
2624 }
2625#endif
2626
2627#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2628 sgcnt = pci_map_sg (megaCfg->dev,
2629 sgList, scb->SCpnt->use_sg, scb->dma_direction);
2630
2631
2632 if (sgcnt == 0)
2633 printk ("pci_map_sg returned zero!!! ");
2634
2635 for (idx = 0; idx < sgcnt; idx++, sgList++) {
2636
2637 if ((megaCfg->flag & BOARD_64BIT) &&
2638 ((mbox->cmd == MEGA_MBOXCMD_LREAD64) ||
2639 (mbox->cmd == MEGA_MBOXCMD_LWRITE64))) {
2640 scb->sg64List[idx].address = sg_dma_address (sgList);
2641 scb->sg64List[idx].length = sg_dma_len (sgList);
2642 } else {
2643 scb->sgList[idx].address = sg_dma_address (sgList);
2644 scb->sgList[idx].length = sg_dma_len (sgList);
2645 }
2646
2647 }
2648
2649#else
2650 for (idx = 0; idx < scb->SCpnt->use_sg; idx++) {
2651 scb->sgList[idx].address = virt_to_bus (sgList[idx].address);
2652 scb->sgList[idx].length = (u32) sgList[idx].length;
2653 }
2654#endif
2655
2656
2657#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2658 *buffer = scb->dma_sghandle64;
2659 scb->sglist_count = scb->SCpnt->use_sg;
2660#else
2661 *buffer = virt_to_bus (scb->sgList);
2662#endif
2663
2664#if 0
2665 *length = 0;
2666#endif
2667
2668
2669
2670
2671 *length = (u32)scb->SCpnt->request_bufflen;
2672
2673#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2674
2675 return sgcnt;
2676#else
2677
2678 return scb->SCpnt->use_sg;
2679#endif
2680}
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698static int
2699mega_register_mailbox (mega_host_config * megaCfg, u32 paddr)
2700{
2701
2702#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2703 megaCfg->mbox = &megaCfg->mailbox64ptr->mailbox;
2704#else
2705 megaCfg->mbox = &megaCfg->mailbox64.mailbox;
2706#endif
2707
2708#if BITS_PER_LONG==64
2709 megaCfg->mbox = (mega_mailbox *) ((((u64) megaCfg->mbox) + 16) & ((u64) (-1) ^ 0x0F));
2710 megaCfg->adjdmahandle64 = (megaCfg->dma_handle64 + 16) & ((u64) (-1) ^ 0x0F);
2711 megaCfg->mbox64 = (mega_mailbox64 *) ((u_char *) megaCfg->mbox - sizeof (u64));
2712 paddr = (paddr + 4 + 16) & ((u64) (-1) ^ 0x0F);
2713#else
2714 megaCfg->mbox
2715 = (mega_mailbox *) ((((u32) megaCfg->mbox) + 16) & 0xFFFFFFF0);
2716
2717#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2718 megaCfg->adjdmahandle64 = ((megaCfg->dma_handle64 + 16) & 0xFFFFFFF0);
2719#endif
2720
2721 megaCfg->mbox64 = (mega_mailbox64 *) ((u_char *) megaCfg->mbox - 8);
2722 paddr = (paddr + 4 + 16) & 0xFFFFFFF0;
2723#endif
2724
2725
2726 if (!(megaCfg->flag & BOARD_QUARTZ)) {
2727 WRITE_PORT (megaCfg->host->io_port, MBOX_PORT0, paddr & 0xFF);
2728 WRITE_PORT (megaCfg->host->io_port, MBOX_PORT1,
2729 (paddr >> 8) & 0xFF);
2730 WRITE_PORT (megaCfg->host->io_port, MBOX_PORT2,
2731 (paddr >> 16) & 0xFF);
2732 WRITE_PORT (megaCfg->host->io_port, MBOX_PORT3,
2733 (paddr >> 24) & 0xFF);
2734 WRITE_PORT (megaCfg->host->io_port, ENABLE_MBOX_REGION,
2735 ENABLE_MBOX_BYTE);
2736
2737 CLEAR_INTR (megaCfg->host->io_port);
2738 ENABLE_INTR (megaCfg->host->io_port);
2739 }
2740 return 0;
2741}
2742
2743
2744
2745
2746
2747static void mega_Convert8ldTo40ld (mega_RAIDINQ * inquiry,
2748 mega_Enquiry3 * enquiry3,
2749 megaRaidProductInfo * productInfo)
2750{
2751 int i;
2752
2753 productInfo->MaxConcCmds = inquiry->AdpInfo.MaxConcCmds;
2754 enquiry3->rbldRate = inquiry->AdpInfo.RbldRate;
2755 productInfo->SCSIChanPresent = inquiry->AdpInfo.ChanPresent;
2756
2757 for (i = 0; i < 4; i++) {
2758 productInfo->FwVer[i] = inquiry->AdpInfo.FwVer[i];
2759 productInfo->BiosVer[i] = inquiry->AdpInfo.BiosVer[i];
2760 }
2761 enquiry3->cacheFlushInterval = inquiry->AdpInfo.CacheFlushInterval;
2762 productInfo->DramSize = inquiry->AdpInfo.DramSize;
2763
2764 enquiry3->numLDrv = inquiry->LogdrvInfo.NumLDrv;
2765
2766 for (i = 0; i < MAX_LOGICAL_DRIVES; i++) {
2767 enquiry3->lDrvSize[i] = inquiry->LogdrvInfo.LDrvSize[i];
2768 enquiry3->lDrvProp[i] = inquiry->LogdrvInfo.LDrvProp[i];
2769 enquiry3->lDrvState[i]
2770 = inquiry->LogdrvInfo.LDrvState[i];
2771 }
2772
2773 for (i = 0; i < (MAX_PHYSICAL_DRIVES); i++) {
2774 enquiry3->pDrvState[i]
2775 = inquiry->PhysdrvInfo.PDrvState[i];
2776 }
2777}
2778
2779
2780
2781
2782static int mega_i_query_adapter (mega_host_config * megaCfg)
2783{
2784 mega_Enquiry3 *enquiry3Pnt;
2785 mega_mailbox *mbox;
2786 u_char mboxData[16];
2787
2788#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2789 dma_addr_t raid_inq_dma_handle = 0, prod_info_dma_handle = 0, enquiry3_dma_handle = 0;
2790#endif
2791 u8 retval;
2792
2793
2794
2795 mbox = (mega_mailbox *) mboxData;
2796
2797 memset ((void *) megaCfg->mega_buffer, 0,
2798 sizeof (megaCfg->mega_buffer));
2799 memset (mbox, 0, 16);
2800
2801
2802
2803
2804
2805
2806#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2807 enquiry3_dma_handle = pci_map_single (megaCfg->dev,
2808 (void *) megaCfg->mega_buffer,
2809 (2 * 1024L), PCI_DMA_FROMDEVICE);
2810
2811 mbox->xferaddr = enquiry3_dma_handle;
2812#else
2813
2814 mbox->xferaddr = virt_to_bus ((void *) megaCfg->mega_buffer);
2815#endif
2816
2817
2818 enquiry3Pnt = (mega_Enquiry3 *) megaCfg->mega_buffer;
2819
2820
2821 mboxData[0] = FC_NEW_CONFIG;
2822 mboxData[2] = NC_SUBOP_ENQUIRY3;
2823 mboxData[3] = ENQ3_GET_SOLICITED_FULL;
2824
2825
2826 if ((retval = megaIssueCmd (megaCfg, mboxData, NULL, 0)) != 0) {
2827 mega_RAIDINQ adapterInquiryData;
2828 mega_RAIDINQ *adapterInquiryPnt = &adapterInquiryData;
2829
2830#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2831 raid_inq_dma_handle = pci_map_single (megaCfg->dev,
2832 (void *) adapterInquiryPnt,
2833 sizeof (mega_RAIDINQ),
2834 PCI_DMA_FROMDEVICE);
2835 mbox->xferaddr = raid_inq_dma_handle;
2836#else
2837
2838 mbox->xferaddr = virt_to_bus ((void *) adapterInquiryPnt);
2839#endif
2840
2841 mbox->cmd = MEGA_MBOXCMD_ADAPTERINQ;
2842 ;
2843 retval = megaIssueCmd (megaCfg, mboxData, NULL, 0);
2844
2845 pci_unmap_single (megaCfg->dev,
2846 raid_inq_dma_handle,
2847 sizeof (mega_RAIDINQ), PCI_DMA_FROMDEVICE);
2848
2849
2850 mega_Convert8ldTo40ld (adapterInquiryPnt,
2851 enquiry3Pnt,
2852 (megaRaidProductInfo *) & megaCfg->
2853 productInfo);
2854
2855 } else {
2856 megaCfg->flag |= BOARD_40LD;
2857
2858 pci_unmap_single (megaCfg->dev,
2859 enquiry3_dma_handle,
2860 (2 * 1024L), PCI_DMA_FROMDEVICE);
2861#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2862
2863 prod_info_dma_handle
2864 = pci_map_single (megaCfg->dev,
2865 (void *) &megaCfg->productInfo,
2866 sizeof (megaRaidProductInfo),
2867 PCI_DMA_FROMDEVICE);
2868 mbox->xferaddr = prod_info_dma_handle;
2869#else
2870
2871 mbox->xferaddr = virt_to_bus ((void *) &megaCfg->productInfo);
2872#endif
2873
2874 mboxData[0] = FC_NEW_CONFIG;
2875 mboxData[2] = NC_SUBOP_PRODUCT_INFO;
2876
2877 if ((retval = megaIssueCmd (megaCfg, mboxData, NULL, 0)) != 0)
2878 printk ("megaraid: Product_info cmd failed with error: %d\n",
2879 retval);
2880
2881 pci_unmap_single (megaCfg->dev,
2882 prod_info_dma_handle,
2883 sizeof (megaRaidProductInfo),
2884 PCI_DMA_FROMDEVICE);
2885 }
2886
2887
2888
2889
2890 megaCfg->host->max_channel =
2891 megaCfg->productInfo.SCSIChanPresent + NVIRT_CHAN -1;
2892
2893 megaCfg->host->max_id = 16;
2894
2895 megaCfg->host->max_lun = 7;
2896
2897 megaCfg->host->cmd_per_lun = MAX_CMD_PER_LUN;
2898
2899 megaCfg->numldrv = enquiry3Pnt->numLDrv;
2900 megaCfg->max_cmds = megaCfg->productInfo.MaxConcCmds;
2901 if (megaCfg->max_cmds > MAX_COMMANDS)
2902 megaCfg->max_cmds = MAX_COMMANDS - 1;
2903
2904 megaCfg->host->can_queue = megaCfg->max_cmds - 1;
2905
2906
2907 if (megaCfg->productInfo.subSystemVendorID == HP_SUBSYS_ID) {
2908 sprintf (megaCfg->fwVer, "%c%d%d.%d%d",
2909 megaCfg->productInfo.FwVer[2],
2910 megaCfg->productInfo.FwVer[1] >> 8,
2911 megaCfg->productInfo.FwVer[1] & 0x0f,
2912 megaCfg->productInfo.FwVer[0] >> 8,
2913 megaCfg->productInfo.FwVer[0] & 0x0f);
2914 sprintf (megaCfg->biosVer, "%c%d%d.%d%d",
2915 megaCfg->productInfo.BiosVer[2],
2916 megaCfg->productInfo.BiosVer[1] >> 8,
2917 megaCfg->productInfo.BiosVer[1] & 0x0f,
2918 megaCfg->productInfo.BiosVer[0] >> 8,
2919 megaCfg->productInfo.BiosVer[0] & 0x0f);
2920 } else {
2921 memcpy (megaCfg->fwVer, (char *) megaCfg->productInfo.FwVer, 4);
2922 megaCfg->fwVer[4] = 0;
2923
2924 memcpy (megaCfg->biosVer, (char *) megaCfg->productInfo.BiosVer, 4);
2925 megaCfg->biosVer[4] = 0;
2926 }
2927 megaCfg->support_ext_cdb = mega_support_ext_cdb(megaCfg);
2928
2929 printk (KERN_NOTICE "megaraid: [%s:%s] detected %d logical drives" M_RD_CRLFSTR,
2930 megaCfg->fwVer, megaCfg->biosVer, megaCfg->numldrv);
2931
2932 if ( megaCfg->support_ext_cdb ) {
2933 printk(KERN_NOTICE "megaraid: supports extended CDBs.\n");
2934 }
2935
2936
2937
2938
2939
2940
2941 return 0;
2942}
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954int megaraid_proc_info (char *buffer, char **start, off_t offset,
2955 int length, int host_no, int inout)
2956{
2957 *start = buffer;
2958 return 0;
2959}
2960
2961static int mega_findCard (Scsi_Host_Template * pHostTmpl,
2962 u16 pciVendor, u16 pciDev, long flag)
2963{
2964 mega_host_config *megaCfg = NULL;
2965 struct Scsi_Host *host = NULL;
2966 u_char pciBus, pciDevFun, megaIrq;
2967
2968 u16 magic;
2969#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2970 u32 magic64;
2971#endif
2972
2973 int i, j;
2974
2975 unsigned long megaBase;
2976 unsigned long tbase;
2977
2978 u16 pciIdx = 0;
2979 u16 numFound = 0;
2980 u16 subsysid, subsysvid;
2981 u8 did_mem_map_f = 0;
2982 u8 did_io_map_f = 0;
2983 u8 did_scsi_register_f = 0;
2984
2985#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
2986 while (!pcibios_find_device
2987 (pciVendor, pciDev, pciIdx, &pciBus, &pciDevFun)) {
2988#else
2989
2990#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)
2991 struct pci_dev *pdev = NULL;
2992#else
2993 struct pci_dev *pdev = pci_devices;
2994#endif
2995
2996 while ((pdev = pci_find_device (pciVendor, pciDev, pdev))) {
2997 if(pci_enable_device (pdev))
2998 continue;
2999 pciBus = pdev->bus->number;
3000 pciDevFun = pdev->devfn;
3001#endif
3002
3003
3004
3005
3006
3007 pdev->dma_mask = 0xFFFFFFFF;
3008
3009 did_mem_map_f = 0;
3010 did_io_map_f = 0;
3011 did_scsi_register_f = 0;
3012
3013 if ((flag & BOARD_QUARTZ) && (skip_id == -1)) {
3014 if( (pciVendor == PCI_VENDOR_ID_PERC4_DI_YSTONE &&
3015 pciDev == PCI_DEVICE_ID_PERC4_DI_YSTONE) ||
3016 (pciVendor == PCI_VENDOR_ID_PERC4_QC_VERDE &&
3017 pciDev == PCI_DEVICE_ID_PERC4_QC_VERDE) ) {
3018
3019 flag |= BOARD_64BIT;
3020 }
3021 else {
3022 pci_read_config_word (pdev, PCI_CONF_AMISIG, &magic);
3023 if ((magic != AMI_SIGNATURE)
3024 && (magic != AMI_SIGNATURE_471)) {
3025 pciIdx++;
3026 continue;
3027 }
3028#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3029 pci_read_config_dword (pdev, PCI_CONF_AMISIG64, &magic64);
3030
3031 if (magic64 == AMI_64BIT_SIGNATURE)
3032 flag |= BOARD_64BIT;
3033#endif
3034 }
3035 }
3036
3037
3038
3039
3040 if (flag & BOARD_QUARTZ) {
3041
3042#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
3043 pcibios_read_config_word (pciBus, pciDevFun,
3044 PCI_SUBSYSTEM_VENDOR_ID,
3045 &subsysvid);
3046 pcibios_read_config_word (pciBus, pciDevFun,
3047 PCI_SUBSYSTEM_ID, &subsysid);
3048#else
3049 pci_read_config_word (pdev,
3050 PCI_SUBSYSTEM_VENDOR_ID,
3051 &subsysvid);
3052 pci_read_config_word (pdev,
3053 PCI_SUBSYSTEM_ID, &subsysid);
3054#endif
3055
3056
3057
3058
3059
3060 if( (subsysvid != AMI_SUBSYS_ID) &&
3061 (subsysvid != DELL_SUBSYS_ID) &&
3062 (subsysvid != LSI_SUBSYS_ID) &&
3063 (subsysvid != INTEL_SUBSYS_ID) &&
3064 (subsysvid != HP_SUBSYS_ID) ) continue;
3065
3066 }
3067
3068 printk (KERN_NOTICE
3069 "megaraid: found 0x%4.04x:0x%4.04x:idx %d:bus %d:slot %d:func %d\n",
3070 pciVendor, pciDev, pciIdx, pciBus, PCI_SLOT (pciDevFun),
3071 PCI_FUNC (pciDevFun));
3072
3073#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
3074 pcibios_read_config_dword (pciBus, pciDevFun,
3075 PCI_BASE_ADDRESS_0,
3076 (u_int *) & megaBase);
3077 pcibios_read_config_byte (pciBus, pciDevFun,
3078 PCI_INTERRUPT_LINE, &megaIrq);
3079#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
3080 megaBase = pdev->base_address[0];
3081 megaIrq = pdev->irq;
3082#else
3083
3084 megaBase = pci_resource_start (pdev, 0);
3085 megaIrq = pdev->irq;
3086#endif
3087
3088 tbase = megaBase;
3089
3090 pciIdx++;
3091
3092 if (flag & BOARD_QUARTZ) {
3093
3094 megaBase &= PCI_BASE_ADDRESS_MEM_MASK;
3095
3096 if( ! request_mem_region(megaBase, 128,
3097 "MegaRAID: LSI Logic Corporation" ) ) {
3098
3099 printk(KERN_WARNING "megaraid: mem region busy!\n");
3100
3101 continue;
3102 }
3103
3104 megaBase = (long) ioremap (megaBase, 128);
3105
3106 if (!megaBase) {
3107
3108 printk(KERN_WARNING "megaraid: could not map hba memory!\n");
3109
3110 release_mem_region(tbase, 128);
3111
3112 continue;
3113 }
3114 did_mem_map_f = 1;
3115
3116 } else {
3117 megaBase &= PCI_BASE_ADDRESS_IO_MASK;
3118 megaBase += 0x10;
3119
3120 if( ! request_region(megaBase, 16,
3121 "MegaRAID: LSI Logic Corporation") ) {
3122
3123 printk(KERN_WARNING "megaraid: region busy.\n");
3124
3125 continue;
3126 }
3127 did_io_map_f = 1;
3128
3129 }
3130
3131
3132 host = scsi_register (pHostTmpl, sizeof (mega_host_config));
3133 if (!host)
3134 goto fail_attach;
3135
3136 did_scsi_register_f = 1;
3137
3138
3139
3140
3141
3142
3143
3144 host->max_sectors = 128;
3145
3146 scsi_set_pci_device(host, pdev);
3147 megaCfg = (mega_host_config *) host->hostdata;
3148 memset (megaCfg, 0, sizeof (mega_host_config));
3149
3150 printk (KERN_NOTICE "scsi%d : Found a MegaRAID controller at 0x%x, IRQ: %d"
3151 M_RD_CRLFSTR, host->host_no, (u_int) megaBase, megaIrq);
3152
3153 if (flag & BOARD_64BIT)
3154 printk (KERN_NOTICE "scsi%d : Enabling 64 bit support\n",
3155 host->host_no);
3156
3157
3158 megaCfg->qCompletedH = NULL;
3159 megaCfg->qCompletedT = NULL;
3160 megaCfg->qPendingH = NULL;
3161 megaCfg->qPendingT = NULL;
3162 megaCfg->qFreeH = NULL;
3163 megaCfg->qFreeT = NULL;
3164 megaCfg->qFcnt = 0;
3165 megaCfg->qPcnt = 0;
3166 megaCfg->qCcnt = 0;
3167 megaCfg->lock_free = SPIN_LOCK_UNLOCKED;
3168 megaCfg->lock_pend = SPIN_LOCK_UNLOCKED;
3169 megaCfg->lock_scsicmd = SPIN_LOCK_UNLOCKED;
3170 megaCfg->flag = flag;
3171 megaCfg->int_qh = NULL;
3172 megaCfg->int_qt = NULL;
3173 megaCfg->int_qlen = 0;
3174
3175#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3176 megaCfg->dev = pdev;
3177#endif
3178 megaCfg->host = host;
3179 megaCfg->base = megaBase;
3180 megaCfg->host->irq = megaIrq;
3181 megaCfg->host->io_port = megaBase;
3182 megaCfg->host->n_io_port = 16;
3183 megaCfg->host->unique_id = (pciBus << 8) | pciDevFun;
3184 megaCtlrs[numCtlrs] = megaCfg;
3185
3186 if (flag & BOARD_QUARTZ) {
3187 megaCfg->host->base = tbase;
3188 }
3189
3190
3191 if (request_irq (megaIrq, megaraid_isr, SA_SHIRQ,
3192 "megaraid", megaCfg)) {
3193 printk (KERN_WARNING
3194 "megaraid: Couldn't register IRQ %d!\n",
3195 megaIrq);
3196 goto fail_attach;
3197 }
3198
3199#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3200
3201
3202
3203
3204
3205 megaCfg->mailbox64ptr
3206 = pci_alloc_consistent (megaCfg->dev,
3207 sizeof (mega_mailbox64),
3208 &(megaCfg->dma_handle64));
3209
3210 mega_register_mailbox (megaCfg,megaCfg->dma_handle64);
3211#else
3212 mega_register_mailbox (megaCfg,
3213 virt_to_bus ((void *) &megaCfg->
3214 mailbox64));
3215#endif
3216
3217 mega_i_query_adapter (megaCfg);
3218
3219 if ((subsysid == 0x1111) && (subsysvid == 0x1111)) {
3220
3221
3222
3223
3224 if( strcmp(megaCfg->fwVer, "3.00") == 0 ||
3225 strcmp(megaCfg->fwVer, "3.01") == 0 ) {
3226
3227 printk( KERN_WARNING
3228 "megaraid: Your card is a Dell PERC 2/SC RAID controller "
3229 "with firmware\nmegaraid: 3.00 or 3.01. This driver is "
3230 "known to have corruption issues\nmegaraid: with those "
3231 "firmware versions on this specific card. In order\n"
3232 "megaraid: to protect your data, please upgrade your "
3233 "firmware to version\nmegaraid: 3.10 or later, available "
3234 "from the Dell Technical Support web\nmegaraid: site at\n"
3235 "http://support.dell.com/us/en/filelib/download/"
3236 "index.asp?fileid=2940\n"
3237 );
3238 }
3239 }
3240
3241
3242
3243
3244
3245
3246
3247 if( (subsysvid == HP_SUBSYS_ID) &&
3248 ((subsysid == 0x60E7)||(subsysid == 0x60E8)) ) {
3249
3250
3251
3252
3253 if( strcmp(megaCfg->fwVer, "H01.07") == 0 ||
3254 strcmp(megaCfg->fwVer, "H01.08") == 0 ||
3255 strcmp(megaCfg->fwVer, "H01.09") == 0 )
3256 {
3257 printk(KERN_WARNING
3258 "megaraid: Firmware H.01.07/8/9 on 1M/2M "
3259 "controllers\nmegaraid: do not support 64 bit "
3260 "addressing.\n"
3261 "megaraid: DISABLING 64 bit support.\n");
3262 megaCfg->flag &= ~BOARD_64BIT;
3263 }
3264 }
3265
3266 if (mega_is_bios_enabled (megaCfg)) {
3267 mega_hbas[numCtlrs].is_bios_enabled = 1;
3268 }
3269
3270
3271
3272
3273 mega_enum_raid_scsi(megaCfg);
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283 mega_get_boot_drv(megaCfg);
3284
3285 if( ! megaCfg->boot_pdrv_enabled ) {
3286 for( i = 0; i < NVIRT_CHAN; i++ )
3287 megaCfg->logdrv_chan[i] = 1;
3288
3289 for( i = NVIRT_CHAN; i < MAX_CHANNEL + NVIRT_CHAN; i++ )
3290 megaCfg->logdrv_chan[i] = 0;
3291
3292 megaCfg->mega_ch_class <<= NVIRT_CHAN;
3293 }
3294 else {
3295 j = megaCfg->productInfo.SCSIChanPresent;
3296 for( i = 0; i < j; i++ )
3297 megaCfg->logdrv_chan[i] = 0;
3298
3299 for( i = j; i < NVIRT_CHAN + j; i++ )
3300 megaCfg->logdrv_chan[i] = 1;
3301 }
3302
3303
3304 mega_hbas[numCtlrs].hostdata_addr = megaCfg;
3305
3306
3307
3308
3309 megaCfg->read_ldidmap = 0;
3310 megaCfg->support_random_del = mega_support_random_del(megaCfg);
3311
3312
3313 if (mega_init_scb (megaCfg)) {
3314 pci_free_consistent (megaCfg->dev,
3315 sizeof (mega_mailbox64),
3316 (void *) megaCfg->mailbox64ptr,
3317 megaCfg->dma_handle64);
3318 goto fail_attach;
3319 }
3320
3321
3322
3323
3324
3325
3326
3327 i = numCtlrs;
3328 numCtlrs++;
3329
3330 mcontroller[i].base = megaBase;
3331 mcontroller[i].irq = megaIrq;
3332 mcontroller[i].numldrv = megaCfg->numldrv;
3333 mcontroller[i].pcibus = pciBus;
3334 mcontroller[i].pcidev = pciDev;
3335 mcontroller[i].pcifun = PCI_FUNC (pciDevFun);
3336 mcontroller[i].pciid = pciIdx;
3337 mcontroller[i].pcivendor = pciVendor;
3338 mcontroller[i].pcislot = PCI_SLOT (pciDevFun);
3339 mcontroller[i].uid = (pciBus << 8) | pciDevFun;
3340
3341 numFound++;
3342
3343
3344#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3345 if ((megaCfg->flag & BOARD_64BIT) && BITS_PER_LONG == 64)
3346#if BITS_PER_LONG==64
3347 pdev->dma_mask = 0xffffffffffffffff;
3348#else
3349 pdev->dma_mask = 0xffffffff;
3350#endif
3351#endif
3352 continue;
3353fail_attach:
3354 if( did_mem_map_f ) {
3355 iounmap((void *)megaBase);
3356 release_mem_region(tbase, 128);
3357 }
3358 if( did_io_map_f ) {
3359 release_region(megaBase, 16);
3360 }
3361 if( did_scsi_register_f ) {
3362 scsi_unregister (host);
3363 }
3364 }
3365 return numFound;
3366}
3367
3368
3369
3370
3371
3372int megaraid_detect (Scsi_Host_Template * pHostTmpl)
3373{
3374 int ctlridx = 0, count = 0;
3375
3376#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
3377 pHostTmpl->proc_dir = &proc_scsi_megaraid;
3378#else
3379 pHostTmpl->proc_name = "megaraid";
3380#endif
3381
3382#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
3383 if (!pcibios_present ()) {
3384 printk (KERN_WARNING "megaraid: PCI bios not present."
3385 M_RD_CRLFSTR);
3386 return 0;
3387 }
3388#endif
3389 skip_id = -1;
3390 if (megaraid && !strncmp (megaraid, "skip", strlen ("skip"))) {
3391 if (megaraid[4] != '\0') {
3392 skip_id = megaraid[4] - '0';
3393 if (megaraid[5] != '\0') {
3394 skip_id = (skip_id * 10) + (megaraid[5] - '0');
3395 }
3396 }
3397 skip_id = (skip_id > 15) ? -1 : skip_id;
3398 }
3399
3400 printk (KERN_NOTICE "megaraid: " MEGARAID_VERSION);
3401
3402 memset (mega_hbas, 0, sizeof (mega_hbas));
3403
3404
3405 count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_DISCOVERY,
3406 PCI_DEVICE_ID_DISCOVERY, BOARD_QUARTZ);
3407 count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_PERC4_DI_YSTONE,
3408 PCI_DEVICE_ID_PERC4_DI_YSTONE, BOARD_QUARTZ);
3409
3410 count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_AMI,
3411 PCI_DEVICE_ID_AMI_MEGARAID, 0);
3412 count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_AMI,
3413 PCI_DEVICE_ID_AMI_MEGARAID2, 0);
3414 count += mega_findCard (pHostTmpl, 0x8086,
3415 PCI_DEVICE_ID_AMI_MEGARAID3, BOARD_QUARTZ);
3416 count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_AMI,
3417 PCI_DEVICE_ID_AMI_MEGARAID3, BOARD_QUARTZ);
3418 count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_LSI_LOGIC,
3419 PCI_DEVICE_ID_AMI_MEGARAID3, BOARD_QUARTZ);
3420 count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_PERC4_QC_VERDE,
3421 PCI_DEVICE_ID_PERC4_QC_VERDE, BOARD_QUARTZ);
3422
3423 mega_reorder_hosts ();
3424
3425#ifdef CONFIG_PROC_FS
3426 if (count) {
3427#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)
3428 mega_proc_dir_entry = proc_mkdir ("megaraid", &proc_root);
3429#else
3430 mega_proc_dir_entry = create_proc_entry ("megaraid",
3431 S_IFDIR | S_IRUGO |
3432 S_IXUGO, &proc_root);
3433#endif
3434 if (!mega_proc_dir_entry)
3435 printk ("megaraid: failed to create megaraid root\n");
3436 else
3437 for (ctlridx = 0; ctlridx < count; ctlridx++)
3438 mega_create_proc_entry (ctlridx,
3439 mega_proc_dir_entry);
3440 }
3441#endif
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452 if (count) {
3453 major = register_chrdev (0, "megadev", &megadev_fops);
3454
3455
3456
3457
3458 if (register_reboot_notifier (&mega_notifier)) {
3459 printk ("MegaRAID Shutdown routine not registered!!\n");
3460 }
3461
3462 init_MUTEX (&mimd_entry_mtx);
3463#ifdef __x86_64__
3464
3465
3466
3467 register_ioctl32_conversion( MEGAIOCCMD, sys_ioctl );
3468#endif
3469 }
3470
3471 return count;
3472}
3473
3474static inline void mega_freeSgList (mega_host_config * megaCfg)
3475{
3476 int i;
3477
3478 for (i = 0; i < megaCfg->max_cmds; i++) {
3479 if (megaCfg->scbList[i].sgList)
3480 pci_free_consistent (megaCfg->dev,
3481 sizeof (mega_64sglist) *
3482 MAX_SGLIST,
3483 megaCfg->scbList[i].sgList,
3484 megaCfg->scbList[i].
3485 dma_sghandle64);
3486#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
3487 kfree (megaCfg->scbList[i].sgList);
3488#endif
3489 }
3490}
3491
3492
3493
3494
3495int megaraid_release (struct Scsi_Host *pSHost)
3496{
3497 mega_host_config *megaCfg;
3498 mega_mailbox *mbox;
3499 u_char mboxData[16];
3500 int i;
3501
3502 megaCfg = (mega_host_config *) pSHost->hostdata;
3503 mbox = (mega_mailbox *) mboxData;
3504
3505
3506 memset (mbox, 0, 16);
3507 mboxData[0] = 0xA;
3508
3509 free_irq (megaCfg->host->irq, megaCfg);
3510
3511
3512
3513 megaIssueCmd (megaCfg, mboxData, NULL, 0);
3514
3515
3516 if (megaCfg->flag & BOARD_QUARTZ) {
3517 iounmap ((void *) megaCfg->base);
3518 release_mem_region(megaCfg->host->base, 128);
3519 } else {
3520 release_region (megaCfg->host->io_port, 16);
3521 }
3522
3523 mega_freeSgList (megaCfg);
3524 pci_free_consistent (megaCfg->dev,
3525 sizeof (mega_mailbox64),
3526 (void *) megaCfg->mailbox64ptr,
3527 megaCfg->dma_handle64);
3528
3529#ifdef CONFIG_PROC_FS
3530 if (megaCfg->controller_proc_dir_entry) {
3531 remove_proc_entry ("stat", megaCfg->controller_proc_dir_entry);
3532 remove_proc_entry ("status",
3533 megaCfg->controller_proc_dir_entry);
3534 remove_proc_entry ("config",
3535 megaCfg->controller_proc_dir_entry);
3536 remove_proc_entry ("mailbox",
3537 megaCfg->controller_proc_dir_entry);
3538 for (i = 0; i < numCtlrs; i++) {
3539 char buf[12] = { 0 };
3540 sprintf (buf, "%d", i);
3541 remove_proc_entry (buf, mega_proc_dir_entry);
3542 }
3543 remove_proc_entry ("megaraid", &proc_root);
3544 }
3545#endif
3546
3547
3548
3549
3550
3551
3552
3553 scsi_unregister (pSHost);
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563 unregister_chrdev (major, "megadev");
3564 unregister_reboot_notifier (&mega_notifier);
3565#ifdef __x86_64__
3566 unregister_ioctl32_conversion( MEGAIOCCMD );
3567#endif
3568
3569 return 0;
3570}
3571
3572static int mega_is_bios_enabled (mega_host_config * megacfg)
3573{
3574 mega_mailbox *mboxpnt;
3575 unsigned char mbox[16];
3576 int ret;
3577
3578 mboxpnt = (mega_mailbox *) mbox;
3579
3580 memset (mbox, 0, sizeof (mbox));
3581 memset ((void *) megacfg->mega_buffer,
3582 0, sizeof (megacfg->mega_buffer));
3583
3584
3585
3586
3587 mbox[0] = IS_BIOS_ENABLED;
3588 mbox[2] = GET_BIOS;
3589
3590 mboxpnt->xferaddr = virt_to_bus ((void *) megacfg->mega_buffer);
3591
3592 ret = megaIssueCmd (megacfg, mbox, NULL, 0);
3593
3594 return (*(char *) megacfg->mega_buffer);
3595}
3596
3597
3598
3599
3600static void
3601mega_enum_raid_scsi(mega_host_config *megacfg)
3602{
3603 mega_mailbox *mboxp;
3604 unsigned char mbox[16];
3605 int i;
3606
3607#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3608 dma_addr_t dma_handle;
3609#endif
3610
3611 mboxp = (mega_mailbox *)mbox;
3612
3613 memset(mbox, 0, sizeof(mbox));
3614
3615
3616
3617 mbox[0] = CHNL_CLASS;
3618 mbox[2] = GET_CHNL_CLASS;
3619
3620 memset((void *)megacfg->mega_buffer, 0, sizeof(megacfg->mega_buffer));
3621
3622#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3623 dma_handle = pci_map_single(megacfg->dev, (void *)megacfg->mega_buffer,
3624 (2 * 1024L), PCI_DMA_FROMDEVICE);
3625
3626 mboxp->xferaddr = dma_handle;
3627#else
3628 mboxp->xferaddr = virt_to_bus((void *)megacfg->mega_buffer);
3629#endif
3630
3631
3632
3633
3634
3635 megacfg->mega_ch_class = 0xFF;
3636 if( megaIssueCmd(megacfg, mbox, NULL, 0) == 0 ) {
3637 megacfg->mega_ch_class = *((char *)megacfg->mega_buffer);
3638 }
3639
3640 for( i = 0; i < megacfg->productInfo.SCSIChanPresent; i++ ) {
3641 if( (megacfg->mega_ch_class >> i) & 0x01 )
3642 printk(KERN_NOTICE"megaraid: channel[%d] is raid.\n", i+1);
3643 else
3644 printk(KERN_NOTICE"megaraid: channel[%d] is scsi.\n", i+1);
3645 }
3646
3647
3648#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3649 pci_unmap_single(megacfg->dev, dma_handle,
3650 (2 * 1024L), PCI_DMA_FROMDEVICE);
3651#endif
3652
3653}
3654
3655
3656
3657
3658
3659void
3660mega_get_boot_drv(mega_host_config *megacfg)
3661{
3662 mega_mailbox *mboxp;
3663 unsigned char mbox[16];
3664 struct private_bios_data *prv_bios_data;
3665 u16 cksum = 0;
3666 u8 *cksum_p;
3667 u8 boot_pdrv;
3668 int i;
3669
3670#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3671 dma_addr_t dma_handle;
3672#endif
3673
3674 mboxp = (mega_mailbox *)mbox;
3675
3676 memset(mbox, 0, sizeof(mbox));
3677
3678 mbox[0] = BIOS_PVT_DATA;
3679 mbox[2] = GET_BIOS_PVT_DATA;
3680
3681 memset((void *)megacfg->mega_buffer, 0, sizeof(megacfg->mega_buffer));
3682
3683#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3684 dma_handle = pci_map_single(megacfg->dev, (void *)megacfg->mega_buffer,
3685 (2 * 1024L), PCI_DMA_FROMDEVICE);
3686
3687 mboxp->xferaddr = dma_handle;
3688#else
3689 mboxp->xferaddr = virt_to_bus((void *)megacfg->mega_buffer);
3690#endif
3691
3692 megacfg->boot_ldrv_enabled = 0;
3693 megacfg->boot_ldrv = 0;
3694
3695 megacfg->boot_pdrv_enabled = 0;
3696 megacfg->boot_pdrv_ch = 0;
3697 megacfg->boot_pdrv_tgt = 0;
3698
3699 if( megaIssueCmd(megacfg, mbox, NULL, 0) == 0 ) {
3700 prv_bios_data = (struct private_bios_data *)megacfg->mega_buffer;
3701
3702 cksum = 0;
3703 cksum_p = (u8 *)prv_bios_data;
3704 for( i = 0; i < 14; i++ ) {
3705 cksum += *cksum_p++;
3706 }
3707
3708 if( prv_bios_data->cksum == (u16)(0-cksum) ) {
3709
3710
3711
3712
3713 if( prv_bios_data->boot_drv & 0x80 ) {
3714 megacfg->boot_pdrv_enabled = 1;
3715 boot_pdrv = prv_bios_data->boot_drv & 0x7F;
3716 megacfg->boot_pdrv_ch = boot_pdrv / 16;
3717 megacfg->boot_pdrv_tgt = boot_pdrv % 16;
3718 }
3719 else {
3720 megacfg->boot_ldrv_enabled = 1;
3721 megacfg->boot_ldrv = prv_bios_data->boot_drv;
3722 }
3723 }
3724 }
3725
3726#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3727 pci_unmap_single(megacfg->dev, dma_handle,
3728 (2 * 1024L), PCI_DMA_FROMDEVICE);
3729#endif
3730
3731}
3732
3733
3734static void mega_reorder_hosts (void)
3735{
3736 struct Scsi_Host *shpnt;
3737 struct Scsi_Host *shone;
3738 struct Scsi_Host *shtwo;
3739 mega_host_config *boot_host;
3740 int i;
3741
3742
3743
3744
3745 boot_host = NULL;
3746 for (i = 0; i < MAX_CONTROLLERS; i++) {
3747 if (mega_hbas[i].is_bios_enabled) {
3748 boot_host = mega_hbas[i].hostdata_addr;
3749 break;
3750 }
3751 }
3752
3753 if (boot_host == NULL) {
3754 printk (KERN_WARNING "megaraid: no BIOS enabled.\n");
3755 return;
3756 }
3757
3758
3759
3760
3761 shone = shtwo = NULL;
3762 for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
3763
3764 for (i = 0; i < MAX_CONTROLLERS; i++) {
3765 if ((mega_host_config *) shpnt->hostdata ==
3766 mega_hbas[i].hostdata_addr) {
3767
3768 if (mega_hbas[i].hostdata_addr == boot_host) {
3769
3770
3771 if (shtwo == NULL)
3772 return;
3773 else {
3774 shone = shpnt;
3775 }
3776 } else {
3777 if (!shtwo) {
3778
3779 shtwo = shpnt;
3780 }
3781 }
3782 break;
3783 }
3784 }
3785
3786
3787
3788
3789 if (shone && shtwo)
3790 break;
3791 }
3792 if (shone && shtwo) {
3793 mega_swap_hosts (shone, shtwo);
3794 }
3795
3796 return;
3797}
3798
3799static void mega_swap_hosts (struct Scsi_Host *shone, struct Scsi_Host *shtwo)
3800{
3801 struct Scsi_Host *prevtoshtwo;
3802 struct Scsi_Host *prevtoshone;
3803 struct Scsi_Host *save = NULL;;
3804
3805
3806 if (shtwo->next == shone) {
3807
3808 if (shtwo == scsi_hostlist && shone->next == NULL) {
3809
3810
3811 scsi_hostlist = shone;
3812 shone->next = shtwo;
3813 shtwo->next = NULL;
3814 } else if (shtwo == scsi_hostlist) {
3815
3816
3817 scsi_hostlist = shone;
3818 shtwo->next = shone->next;
3819 scsi_hostlist->next = shtwo;
3820 } else if (shone->next == NULL) {
3821
3822
3823 prevtoshtwo = scsi_hostlist;
3824
3825 while (prevtoshtwo->next != shtwo)
3826 prevtoshtwo = prevtoshtwo->next;
3827
3828 prevtoshtwo->next = shone;
3829 shone->next = shtwo;
3830 shtwo->next = NULL;
3831 } else {
3832 prevtoshtwo = scsi_hostlist;
3833
3834 while (prevtoshtwo->next != shtwo)
3835 prevtoshtwo = prevtoshtwo->next;
3836
3837 prevtoshtwo->next = shone;
3838 shtwo->next = shone->next;
3839 shone->next = shtwo;
3840 }
3841
3842 } else if (shtwo == scsi_hostlist && shone->next == NULL) {
3843
3844
3845 prevtoshone = scsi_hostlist;
3846
3847 while (prevtoshone->next != shone)
3848 prevtoshone = prevtoshone->next;
3849
3850 scsi_hostlist = shone;
3851 shone->next = shtwo->next;
3852 prevtoshone->next = shtwo;
3853 shtwo->next = NULL;
3854 } else if (shtwo == scsi_hostlist && shone->next != NULL) {
3855
3856
3857 prevtoshone = scsi_hostlist;
3858 while (prevtoshone->next != shone)
3859 prevtoshone = prevtoshone->next;
3860
3861 scsi_hostlist = shone;
3862 prevtoshone->next = shtwo;
3863 save = shtwo->next;
3864 shtwo->next = shone->next;
3865 shone->next = save;
3866 } else if (shone->next == NULL) {
3867
3868
3869 prevtoshtwo = scsi_hostlist;
3870 prevtoshone = scsi_hostlist;
3871
3872 while (prevtoshtwo->next != shtwo)
3873 prevtoshtwo = prevtoshtwo->next;
3874 while (prevtoshone->next != shone)
3875 prevtoshone = prevtoshone->next;
3876
3877 prevtoshtwo->next = shone;
3878 shone->next = shtwo->next;
3879 prevtoshone->next = shtwo;
3880 shtwo->next = NULL;
3881
3882 } else {
3883 prevtoshtwo = scsi_hostlist;
3884 prevtoshone = scsi_hostlist;
3885 save = NULL;;
3886
3887 while (prevtoshtwo->next != shtwo)
3888 prevtoshtwo = prevtoshtwo->next;
3889 while (prevtoshone->next != shone)
3890 prevtoshone = prevtoshone->next;
3891
3892 prevtoshtwo->next = shone;
3893 save = shone->next;
3894 shone->next = shtwo->next;
3895 prevtoshone->next = shtwo;
3896 shtwo->next = save;
3897 }
3898 return;
3899}
3900
3901
3902
3903
3904const char *megaraid_info (struct Scsi_Host *pSHost)
3905{
3906 static char buffer[512];
3907 mega_host_config *megaCfg;
3908
3909 megaCfg = (mega_host_config *) pSHost->hostdata;
3910
3911 sprintf (buffer,
3912 "LSI Logic MegaRAID %s %d commands %d targs %d chans %d luns",
3913 megaCfg->fwVer, megaCfg->productInfo.MaxConcCmds,
3914 megaCfg->host->max_id-1, megaCfg->host->max_channel,
3915 megaCfg->host->max_lun);
3916 return buffer;
3917}
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934int megaraid_queue (Scsi_Cmnd * SCpnt, void (*pktComp) (Scsi_Cmnd *))
3935{
3936 DRIVER_LOCK_T mega_host_config * megaCfg;
3937 mega_scb *pScb;
3938 char *user_area = NULL;
3939
3940 megaCfg = (mega_host_config *) SCpnt->host->hostdata;
3941 DRIVER_LOCK (megaCfg);
3942
3943#if 0
3944 if (!(megaCfg->flag & (1L << SCpnt->channel))) {
3945 if (SCpnt->channel < megaCfg->productInfo.SCSIChanPresent)
3946 printk ( KERN_NOTICE
3947 "scsi%d: scanning channel %d for devices.\n",
3948 megaCfg->host->host_no, SCpnt->channel);
3949 else
3950 printk ( KERN_NOTICE
3951 "scsi%d: scanning virtual channel %d for logical drives.\n",
3952 megaCfg->host->host_no,
3953 SCpnt->channel-megaCfg->productInfo.SCSIChanPresent+1);
3954
3955 megaCfg->flag |= (1L << SCpnt->channel);
3956 }
3957#endif
3958
3959 SCpnt->scsi_done = pktComp;
3960
3961 if (mega_driver_ioctl (megaCfg, SCpnt))
3962 return 0;
3963
3964
3965 if (megaCfg->flag & IN_ABORT) {
3966 SCpnt->result = (DID_ABORT << 16);
3967
3968 if (megaCfg->qCompletedH == NULL) {
3969 megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
3970 } else {
3971 megaCfg->qCompletedT->host_scribble =
3972 (unsigned char *) SCpnt;
3973 megaCfg->qCompletedT = SCpnt;
3974 }
3975 megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
3976 megaCfg->qCcnt++;
3977
3978 DRIVER_UNLOCK (megaCfg);
3979 return 0;
3980 } else if (megaCfg->flag & IN_RESET) {
3981 SCpnt->result = (DID_RESET << 16);
3982
3983 if (megaCfg->qCompletedH == NULL) {
3984 megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
3985 } else {
3986 megaCfg->qCompletedT->host_scribble =
3987 (unsigned char *) SCpnt;
3988 megaCfg->qCompletedT = SCpnt;
3989 }
3990 megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
3991 megaCfg->qCcnt++;
3992
3993 DRIVER_UNLOCK (megaCfg);
3994 return 0;
3995 }
3996
3997 megaCfg->flag |= IN_QUEUE;
3998
3999 if ((pScb = mega_build_cmd (megaCfg, SCpnt)) != NULL) {
4000
4001
4002
4003
4004
4005
4006 if( ! megaCfg->quiescent ) {
4007
4008 if (megaCfg->qPendingH == NULL) {
4009 megaCfg->qPendingH = megaCfg->qPendingT = pScb;
4010 } else {
4011 megaCfg->qPendingT->next = pScb;
4012 megaCfg->qPendingT = pScb;
4013 }
4014 megaCfg->qPendingT->next = NULL;
4015 megaCfg->qPcnt++;
4016
4017 if (mega_runpendq (megaCfg) == -1) {
4018 DRIVER_UNLOCK (megaCfg);
4019 return 0;
4020 }
4021 }
4022 else {
4023
4024 if (megaCfg->int_qh == NULL) {
4025 megaCfg->int_qh = megaCfg->int_qt = pScb;
4026 } else {
4027 megaCfg->int_qt->next = pScb;
4028 megaCfg->int_qt = pScb;
4029 }
4030 megaCfg->int_qt->next = NULL;
4031 megaCfg->int_qlen++;
4032 }
4033
4034 if (pScb->SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW) {
4035 init_MUTEX_LOCKED (&pScb->ioctl_sem);
4036 spin_unlock_irq (&io_request_lock);
4037 down (&pScb->ioctl_sem);
4038 user_area = (char *)*((u32*)&pScb->SCpnt->cmnd[4]);
4039 if (copy_to_user
4040 (user_area, pScb->buff_ptr, pScb->iDataSize)) {
4041 printk
4042 ("megaraid: Error copying ioctl return value to user buffer.\n");
4043 pScb->SCpnt->result = (DID_ERROR << 16);
4044 }
4045 spin_lock_irq (&io_request_lock);
4046 DRIVER_LOCK (megaCfg);
4047 kfree (pScb->buff_ptr);
4048 pScb->buff_ptr = NULL;
4049 mega_cmd_done (megaCfg, pScb, pScb->SCpnt->result);
4050 mega_rundoneq (megaCfg);
4051 mega_runpendq (megaCfg);
4052 DRIVER_UNLOCK (megaCfg);
4053 }
4054
4055 megaCfg->flag &= ~IN_QUEUE;
4056
4057 }
4058
4059 DRIVER_UNLOCK (megaCfg);
4060 return 0;
4061}
4062
4063
4064
4065
4066volatile static int internal_done_flag = 0;
4067volatile static int internal_done_errcode = 0;
4068
4069static DECLARE_WAIT_QUEUE_HEAD (internal_wait);
4070
4071static void internal_done (Scsi_Cmnd * SCpnt)
4072{
4073 internal_done_errcode = SCpnt->result;
4074 internal_done_flag++;
4075 wake_up (&internal_wait);
4076}
4077
4078
4079
4080int megaraid_command (Scsi_Cmnd * SCpnt)
4081{
4082 internal_done_flag = 0;
4083
4084
4085 megaraid_queue (SCpnt, internal_done);
4086
4087 while (!internal_done_flag) {
4088 interruptible_sleep_on (&internal_wait);
4089 }
4090
4091 return internal_done_errcode;
4092}
4093
4094
4095
4096
4097int megaraid_abort (Scsi_Cmnd * SCpnt)
4098{
4099 mega_host_config *megaCfg;
4100 int rc;
4101 mega_scb *pScb;
4102
4103 rc = SCSI_ABORT_NOT_RUNNING;
4104
4105 megaCfg = (mega_host_config *) SCpnt->host->hostdata;
4106
4107 megaCfg->flag |= IN_ABORT;
4108
4109 for (pScb = megaCfg->qPendingH; pScb; pScb = pScb->next) {
4110 if (pScb->SCpnt == SCpnt) {
4111
4112#if DEBUG
4113 showMbox (pScb);
4114#endif
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129 switch (pScb->state) {
4130 case SCB_ABORTED:
4131 rc = SCSI_ABORT_SNOOZE;
4132 break;
4133 case SCB_ISSUED:
4134 rc = SCSI_ABORT_NOT_RUNNING;
4135 pScb->state = SCB_ABORTED;
4136 break;
4137 case SCB_ACTIVE:
4138 mega_freeSCB (megaCfg, pScb);
4139 SCpnt->result = (DID_ABORT << 16);
4140 if (megaCfg->qCompletedH == NULL) {
4141 megaCfg->qCompletedH =
4142 megaCfg->qCompletedT = SCpnt;
4143 } else {
4144 megaCfg->qCompletedT->host_scribble =
4145 (unsigned char *) SCpnt;
4146 megaCfg->qCompletedT = SCpnt;
4147 }
4148 megaCfg->qCompletedT->host_scribble =
4149 (unsigned char *) NULL;
4150 megaCfg->qCcnt++;
4151 rc = SCSI_ABORT_SUCCESS;
4152 break;
4153 default:
4154 printk
4155 ("megaraid_abort: unknown command state!!\n");
4156 rc = SCSI_ABORT_NOT_RUNNING;
4157 break;
4158 }
4159 break;
4160 }
4161 }
4162
4163 megaCfg->flag &= ~IN_ABORT;
4164
4165#if DEBUG
4166 if (megaCfg->flag & IN_QUEUE)
4167 printk ("ma:flag is in queue\n");
4168 if (megaCfg->qCompletedH == NULL)
4169 printk ("ma:qchead == null\n");
4170#endif
4171
4172
4173
4174
4175
4176
4177 if (megaCfg->qCompletedH) {
4178 SCpnt = megaCfg->qCompletedH;
4179 megaCfg->qCompletedH = (Scsi_Cmnd *) SCpnt->host_scribble;
4180 megaCfg->qCcnt--;
4181
4182 SCpnt->host_scribble = (unsigned char *) NULL;
4183
4184 callDone (SCpnt);
4185 }
4186 mega_rundoneq (megaCfg);
4187
4188 return rc;
4189}
4190
4191
4192
4193
4194
4195int megaraid_reset (Scsi_Cmnd * SCpnt, unsigned int rstflags)
4196{
4197 mega_host_config *megaCfg;
4198 int idx;
4199 int rc;
4200 mega_scb *pScb;
4201
4202 rc = SCSI_RESET_NOT_RUNNING;
4203 megaCfg = (mega_host_config *) SCpnt->host->hostdata;
4204
4205 megaCfg->flag |= IN_RESET;
4206
4207 printk
4208 ("megaraid_RESET: %.08lx cmd=%.02x <c=%d.t=%d.l=%d>, flag = %x\n",
4209 SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel,
4210 SCpnt->target, SCpnt->lun, rstflags);
4211
4212 TRACE (("RESET: %.08lx %.02x <%d.%d.%d>\n",
4213 SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel,
4214 SCpnt->target, SCpnt->lun));
4215
4216
4217
4218
4219 for (idx = 0; idx < megaCfg->max_cmds; idx++) {
4220 if (megaCfg->scbList[idx].state != SCB_FREE) {
4221 SCpnt = megaCfg->scbList[idx].SCpnt;
4222 pScb = &megaCfg->scbList[idx];
4223 if (SCpnt != NULL) {
4224 pScb->state = SCB_RESET;
4225 break;
4226 }
4227 }
4228 }
4229
4230 megaCfg->flag &= ~IN_RESET;
4231
4232 mega_rundoneq (megaCfg);
4233 return rc;
4234}
4235
4236#ifdef CONFIG_PROC_FS
4237
4238static int proc_printf (mega_host_config * megaCfg, const char *fmt, ...)
4239{
4240 va_list args;
4241 int i;
4242
4243 if (megaCfg->procidx > PROCBUFSIZE)
4244 return 0;
4245
4246 va_start (args, fmt);
4247 i = vsprintf ((megaCfg->procbuf + megaCfg->procidx), fmt, args);
4248 va_end (args);
4249
4250 megaCfg->procidx += i;
4251 return i;
4252}
4253
4254static int proc_read_config (char *page, char **start, off_t offset,
4255 int count, int *eof, void *data)
4256{
4257
4258 mega_host_config *megaCfg = (mega_host_config *) data;
4259
4260 *start = page;
4261
4262 if (megaCfg->productInfo.ProductName[0] != 0)
4263 proc_printf (megaCfg, "%s\n", megaCfg->productInfo.ProductName);
4264
4265 proc_printf (megaCfg, "Controller Type: ");
4266
4267 if (megaCfg->flag & BOARD_QUARTZ)
4268 proc_printf (megaCfg, "438/466/467/471/493\n");
4269 else
4270 proc_printf (megaCfg, "418/428/434\n");
4271
4272 if (megaCfg->flag & BOARD_40LD)
4273 proc_printf (megaCfg,
4274 "Controller Supports 40 Logical Drives\n");
4275
4276 if (megaCfg->flag & BOARD_64BIT)
4277 proc_printf (megaCfg,
4278 "Controller / Driver uses 64 bit memory addressing\n");
4279
4280 proc_printf (megaCfg, "Base = %08x, Irq = %d, ", megaCfg->base,
4281 megaCfg->host->irq);
4282
4283 proc_printf (megaCfg, "Logical Drives = %d, Channels = %d\n",
4284 megaCfg->numldrv, megaCfg->productInfo.SCSIChanPresent);
4285
4286 proc_printf (megaCfg, "Version =%s:%s, DRAM = %dMb\n",
4287 megaCfg->fwVer, megaCfg->biosVer,
4288 megaCfg->productInfo.DramSize);
4289
4290 proc_printf (megaCfg,
4291 "Controller Queue Depth = %d, Driver Queue Depth = %d\n",
4292 megaCfg->productInfo.MaxConcCmds, megaCfg->max_cmds);
4293 COPY_BACK;
4294 return count;
4295}
4296
4297static int proc_read_stat (char *page, char **start, off_t offset,
4298 int count, int *eof, void *data)
4299{
4300 mega_host_config *megaCfg = (mega_host_config *) data;
4301
4302 *start = page;
4303
4304 proc_printf (megaCfg, "Statistical Information for this controller\n");
4305 proc_printf (megaCfg, "Interrupts Collected = %lu\n",
4306 megaCfg->nInterrupts);
4307
4308 proc_printf (megaCfg, "INTERFACE DISABLED\n");
4309 COPY_BACK;
4310 return count;
4311
4312#if 0
4313 for (i = 0; i < megaCfg->numldrv; i++) {
4314 proc_printf (megaCfg, "Logical Drive %d:\n", i);
4315
4316 proc_printf (megaCfg,
4317 "\tReads Issued = %lu, Writes Issued = %lu\n",
4318 megaCfg->nReads[i], megaCfg->nWrites[i]);
4319
4320 proc_printf (megaCfg,
4321 "\tSectors Read = %lu, Sectors Written = %lu\n\n",
4322 megaCfg->nReadBlocks[i], megaCfg->nWriteBlocks[i]);
4323
4324 }
4325
4326 COPY_BACK;
4327 return count;
4328#endif
4329}
4330
4331static int proc_read_status (char *page, char **start, off_t offset,
4332 int count, int *eof, void *data)
4333{
4334 mega_host_config *megaCfg = (mega_host_config *) data;
4335 *start = page;
4336
4337 proc_printf (megaCfg, "TBD\n");
4338 COPY_BACK;
4339 return count;
4340}
4341
4342static int proc_read_mbox (char *page, char **start, off_t offset,
4343 int count, int *eof, void *data)
4344{
4345
4346 mega_host_config *megaCfg = (mega_host_config *) data;
4347 volatile mega_mailbox *mbox = megaCfg->mbox;
4348
4349 *start = page;
4350
4351 proc_printf (megaCfg, "Contents of Mail Box Structure\n");
4352 proc_printf (megaCfg, " Fw Command = 0x%02x\n", mbox->cmd);
4353 proc_printf (megaCfg, " Cmd Sequence = 0x%02x\n", mbox->cmdid);
4354 proc_printf (megaCfg, " No of Sectors= %04d\n", mbox->numsectors);
4355 proc_printf (megaCfg, " LBA = 0x%02x\n", mbox->lba);
4356 proc_printf (megaCfg, " DTA = 0x%08x\n", mbox->xferaddr);
4357 proc_printf (megaCfg, " Logical Drive= 0x%02x\n", mbox->logdrv);
4358 proc_printf (megaCfg, " No of SG Elmt= 0x%02x\n", mbox->numsgelements);
4359 proc_printf (megaCfg, " Busy = %01x\n", mbox->busy);
4360 proc_printf (megaCfg, " Status = 0x%02x\n", mbox->status);
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382 COPY_BACK;
4383 return count;
4384}
4385
4386#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)
4387#define CREATE_READ_PROC(string, fxn) create_proc_read_entry(string, \
4388 S_IRUSR | S_IFREG,\
4389 controller_proc_dir_entry,\
4390 fxn, megaCfg)
4391#else
4392#define CREATE_READ_PROC(string, fxn) create_proc_read_entry(string,S_IRUSR | S_IFREG, controller_proc_dir_entry, fxn, megaCfg)
4393
4394static struct proc_dir_entry *
4395create_proc_read_entry (const char *string,
4396 int mode,
4397 struct proc_dir_entry *parent,
4398 read_proc_t * fxn, mega_host_config * megaCfg)
4399{
4400 struct proc_dir_entry *temp = NULL;
4401
4402 temp = kmalloc (sizeof (struct proc_dir_entry), GFP_KERNEL);
4403 if (!temp)
4404 return NULL;
4405 memset (temp, 0, sizeof (struct proc_dir_entry));
4406
4407 if ((temp->name = kmalloc (strlen (string) + 1, GFP_KERNEL)) == NULL) {
4408 kfree (temp);
4409 return NULL;
4410 }
4411
4412 strcpy ((char *) temp->name, string);
4413 temp->namelen = strlen (string);
4414 temp->mode = mode; ;
4415 temp->data = (void *) megaCfg;
4416 temp->read_proc = fxn;
4417 proc_register (parent, temp);
4418 return temp;
4419}
4420#endif
4421
4422static void mega_create_proc_entry (int index, struct proc_dir_entry *parent)
4423{
4424 u_char string[64] = { 0 };
4425 mega_host_config *megaCfg = megaCtlrs[index];
4426 struct proc_dir_entry *controller_proc_dir_entry = NULL;
4427
4428 sprintf (string, "%d", index);
4429
4430#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)
4431 controller_proc_dir_entry =
4432 megaCfg->controller_proc_dir_entry = proc_mkdir (string, parent);
4433#else
4434 controller_proc_dir_entry =
4435 megaCfg->controller_proc_dir_entry =
4436 create_proc_entry (string, S_IFDIR | S_IRUGO | S_IXUGO, parent);
4437#endif
4438
4439 if (!controller_proc_dir_entry)
4440 printk ("\nmegaraid: proc_mkdir failed\n");
4441 else {
4442 megaCfg->proc_read =
4443 CREATE_READ_PROC ("config", proc_read_config);
4444 megaCfg->proc_status =
4445 CREATE_READ_PROC ("status", proc_read_status);
4446 megaCfg->proc_stat = CREATE_READ_PROC ("stat", proc_read_stat);
4447 megaCfg->proc_mbox =
4448 CREATE_READ_PROC ("mailbox", proc_read_mbox);
4449 }
4450
4451}
4452#endif
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464int megaraid_biosparam (Disk * disk, kdev_t dev, int *geom)
4465{
4466 int heads, sectors, cylinders;
4467 mega_host_config *megaCfg;
4468
4469
4470 megaCfg = (mega_host_config *) disk->device->host->hostdata;
4471
4472 if( IS_RAID_CH(megaCfg, disk->device->channel)) {
4473
4474 heads = 64;
4475 sectors = 32;
4476 cylinders = disk->capacity / (heads * sectors);
4477
4478
4479 if (disk->capacity >= 0x200000) {
4480 heads = 255;
4481 sectors = 63;
4482 cylinders = disk->capacity / (heads * sectors);
4483 }
4484
4485
4486 geom[0] = heads;
4487 geom[1] = sectors;
4488 geom[2] = cylinders;
4489 }
4490 else {
4491 if( mega_partsize(disk, dev, geom) == 0 ) return 0;
4492
4493 printk(KERN_WARNING
4494 "megaraid: invalid partition on this disk on channel %d\n",
4495 disk->device->channel);
4496
4497
4498 heads = 64;
4499 sectors = 32;
4500 cylinders = disk->capacity / (heads * sectors);
4501
4502
4503 if (disk->capacity >= 0x200000) {
4504 heads = 255;
4505 sectors = 63;
4506 cylinders = disk->capacity / (heads * sectors);
4507 }
4508
4509
4510 geom[0] = heads;
4511 geom[1] = sectors;
4512 geom[2] = cylinders;
4513 }
4514
4515 return 0;
4516}
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528static int
4529mega_partsize(Disk * disk, kdev_t dev, int *geom)
4530{
4531 struct buffer_head *bh;
4532 struct partition *p, *largest = NULL;
4533 int i, largest_cyl;
4534 int heads, cyls, sectors;
4535 int capacity = disk->capacity;
4536
4537 int ma = MAJOR(dev);
4538 int mi = (MINOR(dev) & ~0xf);
4539
4540 int block = 1024;
4541
4542 if(blksize_size[ma])
4543 block = blksize_size[ma][mi];
4544
4545 if(!(bh = bread(MKDEV(ma,mi), 0, block)))
4546 return -1;
4547
4548 if( *(unsigned short *)(bh->b_data + 510) == 0xAA55 ) {
4549
4550 for( largest_cyl = -1, p = (struct partition *)(0x1BE + bh->b_data),
4551 i = 0; i < 4; ++i, ++p) {
4552
4553 if (!p->sys_ind) continue;
4554
4555 cyls = p->end_cyl + ((p->end_sector & 0xc0) << 2);
4556
4557 if(cyls >= largest_cyl) {
4558 largest_cyl = cyls;
4559 largest = p;
4560 }
4561 }
4562 }
4563
4564 if (largest) {
4565 heads = largest->end_head + 1;
4566 sectors = largest->end_sector & 0x3f;
4567
4568 if (heads == 0 || sectors == 0) {
4569 brelse(bh);
4570 return -1;
4571 }
4572
4573 cyls = capacity/(heads * sectors);
4574
4575 geom[0] = heads;
4576 geom[1] = sectors;
4577 geom[2] = cyls;
4578
4579 brelse(bh);
4580 return 0;
4581 }
4582
4583 brelse(bh);
4584 return -1;
4585}
4586
4587
4588
4589
4590
4591
4592static int megaraid_reboot_notify (struct notifier_block *this, unsigned long code,
4593 void *unused)
4594{
4595 struct Scsi_Host *pSHost;
4596 mega_host_config *megaCfg;
4597 mega_mailbox *mbox;
4598 u_char mboxData[16];
4599 int i;
4600
4601 if (code == SYS_DOWN || code == SYS_HALT) {
4602 for (i = 0; i < numCtlrs; i++) {
4603 pSHost = megaCtlrs[i]->host;
4604
4605 megaCfg = (mega_host_config *) pSHost->hostdata;
4606 mbox = (mega_mailbox *) mboxData;
4607
4608
4609 memset (mbox, 0, 16);
4610 mboxData[0] = 0xA;
4611
4612
4613
4614
4615 free_irq (megaCfg->host->irq, megaCfg);
4616
4617
4618
4619
4620
4621 megaIssueCmd (megaCfg, mboxData, NULL, 0);
4622 }
4623 }
4624 return NOTIFY_DONE;
4625}
4626
4627static int mega_init_scb (mega_host_config * megacfg)
4628{
4629 int idx;
4630
4631#if DEBUG
4632 if (megacfg->max_cmds >= MAX_COMMANDS) {
4633 printk ("megaraid:ctlr max cmds = %x : MAX_CMDS = %x",
4634 megacfg->max_cmds, MAX_COMMANDS);
4635 }
4636#endif
4637
4638 for (idx = megacfg->max_cmds - 1; idx >= 0; idx--) {
4639
4640 megacfg->scbList[idx].idx = idx;
4641
4642
4643
4644
4645
4646
4647
4648#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4649 megacfg->scbList[idx].sgList =
4650 pci_alloc_consistent (megacfg->dev,
4651 sizeof (mega_64sglist) * MAX_SGLIST,
4652 &(megacfg->scbList[idx].
4653 dma_sghandle64));
4654
4655 megacfg->scbList[idx].sg64List =
4656 (mega_64sglist *) megacfg->scbList[idx].sgList;
4657#else
4658 megacfg->scbList[idx].sgList = kmalloc (sizeof (mega_sglist) * MAX_SGLIST, GFP_ATOMIC | GFP_DMA);
4659#endif
4660
4661 if (megacfg->scbList[idx].sgList == NULL) {
4662 printk (KERN_WARNING
4663 "Can't allocate sglist for id %d\n", idx);
4664 mega_freeSgList (megacfg);
4665 return -1;
4666 }
4667#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4668 megacfg->scbList[idx].pthru = pci_alloc_consistent (megacfg->dev,
4669 sizeof (mega_passthru),
4670 &(megacfg->scbList[idx].
4671 dma_passthruhandle64));
4672
4673 if (megacfg->scbList[idx].pthru == NULL) {
4674 printk (KERN_WARNING
4675 "Can't allocate passthru for id %d\n", idx);
4676 }
4677
4678 megacfg->scbList[idx].epthru =
4679 pci_alloc_consistent(
4680 megacfg->dev, sizeof(mega_ext_passthru),
4681 &(megacfg->scbList[idx].dma_ext_passthruhandle64)
4682 );
4683
4684 if (megacfg->scbList[idx].epthru == NULL) {
4685 printk (KERN_WARNING
4686 "Can't allocate extended passthru for id %d\n", idx);
4687 }
4688
4689
4690
4691 megacfg->scbList[idx].bounce_buffer = pci_alloc_consistent (megacfg->dev,
4692 256,
4693 &(megacfg->scbList[idx].
4694 dma_bounce_buffer));
4695
4696 if (!megacfg->scbList[idx].bounce_buffer)
4697 printk
4698 ("megaraid: allocation for bounce buffer failed\n");
4699
4700 megacfg->scbList[idx].dma_type = M_RD_DMA_TYPE_NONE;
4701#endif
4702
4703 if (idx < MAX_COMMANDS) {
4704
4705
4706
4707
4708
4709 enq_scb_freelist (megacfg, &megacfg->scbList[idx],
4710 NO_LOCK, INTR_ENB);
4711
4712 }
4713 }
4714
4715 return 0;
4716}
4717
4718
4719
4720
4721static void enq_scb_freelist (mega_host_config * megacfg, mega_scb * scb, int lock,
4722 int intr)
4723{
4724
4725 if (lock == INTERNAL_LOCK || intr == INTR_DIS) {
4726 if (intr == INTR_DIS)
4727 spin_lock_irq (&megacfg->lock_free);
4728 else
4729 spin_lock (&megacfg->lock_free);
4730 }
4731
4732 scb->state = SCB_FREE;
4733 scb->SCpnt = NULL;
4734
4735 if (megacfg->qFreeH == (mega_scb *) NULL) {
4736 megacfg->qFreeH = megacfg->qFreeT = scb;
4737 } else {
4738 megacfg->qFreeT->next = scb;
4739 megacfg->qFreeT = scb;
4740 }
4741
4742 megacfg->qFreeT->next = NULL;
4743 megacfg->qFcnt++;
4744
4745 if (lock == INTERNAL_LOCK || intr == INTR_DIS) {
4746 if (intr == INTR_DIS)
4747 spin_unlock_irq (&megacfg->lock_free);
4748 else
4749 spin_unlock (&megacfg->lock_free);
4750 }
4751}
4752
4753
4754
4755
4756static int megadev_open (struct inode *inode, struct file *filep)
4757{
4758 MOD_INC_USE_COUNT;
4759 return 0;
4760}
4761
4762static int megadev_ioctl_entry (struct inode *inode, struct file *filep,
4763 unsigned int cmd, unsigned long arg)
4764{
4765 int ret = -1;
4766
4767
4768
4769
4770 down (&mimd_entry_mtx);
4771 ret = megadev_ioctl (inode, filep, cmd, arg);
4772 up (&mimd_entry_mtx);
4773
4774 return ret;
4775
4776}
4777
4778static int megadev_ioctl (struct inode *inode, struct file *filep,
4779 unsigned int cmd, unsigned long arg)
4780{
4781 int adapno;
4782 kdev_t dev;
4783 u32 inlen;
4784 struct uioctl_t ioc;
4785 char *kvaddr = NULL;
4786 int nadap = numCtlrs;
4787 u8 opcode;
4788 u32 outlen;
4789 int ret;
4790 u8 subopcode;
4791 Scsi_Cmnd *scsicmd;
4792 struct Scsi_Host *shpnt;
4793 char *uaddr;
4794 struct uioctl_t *uioc;
4795 dma_addr_t dma_addr;
4796 u32 length;
4797 mega_host_config *megacfg = NULL;
4798#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4799 struct pci_dev pdev;
4800 struct pci_dev *pdevp = &pdev;
4801#else
4802 char *pdevp = NULL;
4803#endif
4804 IO_LOCK_T;
4805
4806 if (!inode || !(dev = inode->i_rdev))
4807 return -EINVAL;
4808
4809 if (_IOC_TYPE (cmd) != MEGAIOC_MAGIC)
4810 return (-EINVAL);
4811
4812
4813
4814
4815 ret = verify_area (VERIFY_WRITE, (char *) arg, sizeof (struct uioctl_t));
4816
4817 if (ret)
4818 return ret;
4819
4820 if(copy_from_user (&ioc, (char *) arg, sizeof (struct uioctl_t)))
4821 return -EFAULT;
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833 opcode = ioc.ui.fcs.opcode;
4834 subopcode = ioc.ui.fcs.subopcode;
4835
4836 switch (opcode) {
4837 case M_RD_DRIVER_IOCTL_INTERFACE:
4838 switch (subopcode) {
4839 case MEGAIOC_QDRVRVER:
4840 put_user (driver_ver, (u32 *) ioc.data);
4841 return 0;
4842
4843 case MEGAIOC_QNADAP:
4844 put_user (nadap, (int *) ioc.data);
4845 return nadap;
4846
4847 case MEGAIOC_QADAPINFO:
4848
4849
4850
4851 adapno = ioc.ui.fcs.adapno;
4852
4853
4854
4855
4856
4857
4858
4859
4860 adapno = GETADAP (adapno);
4861
4862 if (adapno >= numCtlrs)
4863 return (-ENODEV);
4864
4865 ret = verify_area (VERIFY_WRITE,
4866 ioc.data,
4867 sizeof (struct mcontroller));
4868 if (ret)
4869 return ret;
4870
4871
4872
4873
4874 if (copy_to_user (ioc.data,
4875 mcontroller + adapno,
4876 sizeof (struct mcontroller)))
4877 return -EFAULT;
4878 return 0;
4879
4880 default:
4881 return (-EINVAL);
4882
4883 }
4884 break;
4885
4886 case M_RD_IOCTL_CMD_NEW:
4887
4888
4889
4890
4891 if( ioc.mbox[0] == FC_DEL_LOGDRV && ioc.mbox[2] == OP_DEL_LOGDRV ) {
4892 return -EINVAL;
4893 }
4894
4895
4896 adapno = ioc.ui.fcs.adapno;
4897
4898
4899 adapno = GETADAP(adapno);
4900
4901 if (adapno >= numCtlrs)
4902 return(-ENODEV);
4903
4904 length = ioc.ui.fcs.length;
4905
4906
4907 if( !length || length > 32*1024 )
4908 return -EINVAL;
4909
4910
4911 uaddr = ioc.ui.fcs.buffer;
4912
4913
4914
4915
4916
4917
4918
4919 outlen = ioc.outlen;
4920 inlen = ioc.inlen;
4921
4922 if(outlen) {
4923 ret = verify_area(VERIFY_WRITE, (char *)ioc.ui.fcs.buffer, length);
4924 if (ret) return ret;
4925 }
4926 if(inlen) {
4927 ret = verify_area(VERIFY_READ, (char *) ioc.ui.fcs.buffer, length);
4928 if (ret) return ret;
4929 }
4930
4931
4932
4933
4934 for( shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next ) {
4935 if( shpnt->hostdata == (unsigned long *)megaCtlrs[adapno] ) {
4936 megacfg = (mega_host_config *)shpnt->hostdata;
4937 break;
4938 }
4939 }
4940 if(shpnt == NULL) return -ENODEV;
4941
4942#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4943 scsicmd = (Scsi_Cmnd *)kmalloc(sizeof(Scsi_Cmnd), GFP_KERNEL);
4944#else
4945 scsicmd = (Scsi_Cmnd *)scsi_init_malloc(sizeof(Scsi_Cmnd),
4946 GFP_ATOMIC | GFP_DMA);
4947#endif
4948 if(scsicmd == NULL) return -ENOMEM;
4949
4950 memset(scsicmd, 0, sizeof(Scsi_Cmnd));
4951 scsicmd->host = shpnt;
4952
4953 if( outlen || inlen ) {
4954#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4955 pdevp = &pdev;
4956 memcpy(pdevp, megacfg->dev, sizeof(struct pci_dev));
4957 pdevp->dma_mask = 0xffffffff;
4958#else
4959 pdevp = NULL;
4960#endif
4961 kvaddr = dma_alloc_consistent(pdevp, length, &dma_addr);
4962
4963 if( kvaddr == NULL ) {
4964 printk(KERN_WARNING "megaraid:allocation failed\n");
4965 ret = -ENOMEM;
4966 goto out_ioctl_cmd_new;
4967 }
4968
4969 ioc.ui.fcs.buffer = kvaddr;
4970
4971 if (inlen) {
4972
4973 if( copy_from_user(kvaddr, (char *)uaddr, length ) ) {
4974 ret = -EFAULT;
4975 goto out_ioctl_cmd_new;
4976 }
4977 }
4978 }
4979
4980 scsicmd->cmnd[0] = MEGADEVIOC;
4981 scsicmd->request_buffer = (void *)&ioc;
4982
4983 init_MUTEX_LOCKED(&mimd_ioctl_sem);
4984
4985 IO_LOCK;
4986 megaraid_queue(scsicmd, megadev_ioctl_done);
4987
4988 IO_UNLOCK;
4989
4990 down(&mimd_ioctl_sem);
4991
4992 if( !scsicmd->result && outlen ) {
4993 if (copy_to_user(uaddr, kvaddr, length)) {
4994 ret = -EFAULT;
4995 goto out_ioctl_cmd_new;
4996 }
4997 }
4998
4999
5000
5001
5002 uioc = (struct uioctl_t *)arg;
5003
5004 if( ioc.mbox[0] == MEGA_MBOXCMD_PASSTHRU ) {
5005 put_user( scsicmd->result, &uioc->pthru.scsistatus );
5006 if (copy_to_user( uioc->pthru.reqsensearea, scsicmd->sense_buffer,
5007 MAX_REQ_SENSE_LEN ))
5008 ret= -EFAULT;
5009 } else {
5010 put_user(1, &uioc->mbox[16]);
5011
5012 put_user (scsicmd->result, &uioc->mbox[17]);
5013 }
5014
5015out_ioctl_cmd_new:
5016
5017 if (kvaddr) {
5018 dma_free_consistent(pdevp, length, kvaddr, dma_addr);
5019 }
5020#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5021 kfree (scsicmd);
5022#else
5023 scsi_init_free((char *)scsicmd, sizeof(Scsi_Cmnd));
5024#endif
5025
5026
5027 ioc.ui.fcs.buffer = uaddr;
5028
5029 return ret;
5030
5031 case M_RD_IOCTL_CMD:
5032
5033 adapno = ioc.ui.fcs.adapno;
5034
5035
5036 adapno = GETADAP (adapno);
5037
5038 if (adapno >= numCtlrs)
5039 return (-ENODEV);
5040
5041
5042 uaddr = ioc.data;
5043 outlen = ioc.outlen;
5044 inlen = ioc.inlen;
5045
5046 if ((outlen >= IOCTL_MAX_DATALEN) || (inlen >= IOCTL_MAX_DATALEN))
5047 return (-EINVAL);
5048
5049 if (outlen) {
5050 ret = verify_area (VERIFY_WRITE, ioc.data, outlen);
5051 if (ret) return ret;
5052 }
5053 if (inlen) {
5054 ret = verify_area (VERIFY_READ, ioc.data, inlen);
5055 if (ret) return ret;
5056 }
5057
5058
5059
5060
5061 for( shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next ) {
5062 if( shpnt->hostdata == (unsigned long *)megaCtlrs[adapno] ) {
5063 megacfg = (mega_host_config *)shpnt->hostdata;
5064 break;
5065 }
5066 }
5067 if(shpnt == NULL) return -ENODEV;
5068
5069
5070
5071
5072
5073 if( ioc.mbox[0] == FC_DEL_LOGDRV && ioc.mbox[2] == OP_DEL_LOGDRV ) {
5074
5075 if( !megacfg->support_random_del ) {
5076 printk("megaraid: logdrv delete on non supporting f/w.\n");
5077 return -EINVAL;
5078 }
5079
5080 uioc = (struct uioctl_t *)arg;
5081
5082 ret = mega_del_logdrv(megacfg, ioc.mbox[3]);
5083
5084 put_user(1, &uioc->mbox[16]);
5085 put_user(ret, &uioc->mbox[17]);
5086
5087
5088 return ret;
5089 }
5090
5091#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5092 scsicmd = (Scsi_Cmnd *)kmalloc(sizeof(Scsi_Cmnd), GFP_KERNEL);
5093#else
5094 scsicmd = (Scsi_Cmnd *)scsi_init_malloc(sizeof(Scsi_Cmnd),
5095 GFP_ATOMIC | GFP_DMA);
5096#endif
5097 if(scsicmd == NULL) return -ENOMEM;
5098
5099 memset(scsicmd, 0, sizeof(Scsi_Cmnd));
5100 scsicmd->host = shpnt;
5101
5102 if (outlen || inlen) {
5103#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5104 pdevp = &pdev;
5105 memcpy(pdevp, megacfg->dev, sizeof(struct pci_dev));
5106 pdevp->dma_mask = 0xffffffff;
5107#else
5108 pdevp = NULL;
5109#endif
5110
5111
5112
5113 kvaddr = dma_alloc_consistent(pdevp, PAGE_SIZE, &dma_addr);
5114
5115 if( kvaddr == NULL ) {
5116 printk (KERN_WARNING "megaraid:allocation failed\n");
5117 ret = -ENOMEM;
5118 goto out_ioctl_cmd;
5119 }
5120
5121 ioc.data = kvaddr;
5122
5123 if (inlen) {
5124 if (ioc.mbox[0] == MEGA_MBOXCMD_PASSTHRU) {
5125
5126 if( copy_from_user (kvaddr, uaddr, ioc.pthru.dataxferlen)){
5127 ret = -EFAULT;
5128 goto out_ioctl_cmd;
5129 }
5130 } else {
5131 if( copy_from_user (kvaddr, uaddr, inlen) ) {
5132 ret = -EFAULT;
5133 goto out_ioctl_cmd;
5134 }
5135 }
5136 }
5137 }
5138
5139 scsicmd->cmnd[0] = MEGADEVIOC;
5140 scsicmd->request_buffer = (void *) &ioc;
5141
5142 init_MUTEX_LOCKED (&mimd_ioctl_sem);
5143
5144 IO_LOCK;
5145 megaraid_queue (scsicmd, megadev_ioctl_done);
5146
5147 IO_UNLOCK;
5148 down (&mimd_ioctl_sem);
5149
5150 if (!scsicmd->result && outlen) {
5151 if (ioc.mbox[0] == MEGA_MBOXCMD_PASSTHRU) {
5152 if (copy_to_user (uaddr, kvaddr, ioc.pthru.dataxferlen)) {
5153 ret = -EFAULT;
5154 goto out_ioctl_cmd;
5155 }
5156 } else {
5157 if (copy_to_user (uaddr, kvaddr, outlen)) {
5158 ret = -EFAULT;
5159 goto out_ioctl_cmd;
5160 }
5161 }
5162 }
5163
5164
5165
5166
5167 uioc = (struct uioctl_t *) arg;
5168
5169 if (ioc.mbox[0] == MEGA_MBOXCMD_PASSTHRU) {
5170 put_user (scsicmd->result, &uioc->pthru.scsistatus);
5171
5172
5173
5174
5175
5176 if (copy_to_user( uioc->pthru.reqsensearea, scsicmd->sense_buffer,
5177 MAX_REQ_SENSE_LEN ))
5178 ret = -EFAULT;
5179
5180 } else {
5181 put_user (1, &uioc->mbox[16]);
5182 put_user (scsicmd->result, &uioc->mbox[17]);
5183 }
5184
5185out_ioctl_cmd:
5186
5187 if (kvaddr) {
5188 dma_free_consistent(pdevp, PAGE_SIZE, kvaddr, dma_addr );
5189 }
5190
5191#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5192 kfree (scsicmd);
5193#else
5194 scsi_init_free((char *)scsicmd, sizeof(Scsi_Cmnd));
5195#endif
5196
5197
5198 ioc.data = uaddr;
5199
5200 return ret;
5201
5202 default:
5203 return (-EINVAL);
5204
5205 }
5206
5207 return 0;
5208}
5209
5210static void
5211megadev_ioctl_done(Scsi_Cmnd *sc)
5212{
5213 up (&mimd_ioctl_sem);
5214}
5215
5216static mega_scb *
5217megadev_doioctl (mega_host_config * megacfg, Scsi_Cmnd * sc)
5218{
5219 u8 cmd;
5220 struct uioctl_t *ioc = NULL;
5221 mega_mailbox *mbox = NULL;
5222 mega_ioctl_mbox *mboxioc = NULL;
5223 struct mbox_passthru *mboxpthru = NULL;
5224 mega_scb *scb = NULL;
5225 mega_passthru *pthru = NULL;
5226
5227 if ((scb = mega_allocateSCB (megacfg, sc)) == NULL) {
5228 sc->result = (DID_ERROR << 16);
5229 callDone (sc);
5230 return NULL;
5231 }
5232
5233 ioc = (struct uioctl_t *) sc->request_buffer;
5234
5235 memcpy (scb->mboxData, ioc->mbox, sizeof (scb->mboxData));
5236
5237
5238 mbox = (mega_mailbox *) ioc->mbox;
5239
5240
5241
5242
5243 cmd = ioc->mbox[0];
5244
5245 switch (cmd) {
5246 case MEGA_MBOXCMD_PASSTHRU:
5247
5248
5249
5250#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5251 pthru = scb->pthru;
5252#else
5253 pthru = &scb->pthru;
5254#endif
5255 memcpy (pthru, &ioc->pthru, sizeof (mega_passthru));
5256 mboxpthru = (struct mbox_passthru *) scb->mboxData;
5257#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5258 if (megacfg->flag & BOARD_64BIT) {
5259
5260
5261
5262 mboxpthru->dataxferaddr = scb->dma_passthruhandle64;
5263 scb->sg64List[0].address =
5264 pci_map_single (megacfg->dev,
5265 ioc->data,
5266 4096, PCI_DMA_BIDIRECTIONAL);
5267 scb->sg64List[0].length = 4096;
5268 pthru->dataxferaddr = scb->dma_sghandle64;
5269 pthru->numsgelements = 1;
5270 mboxpthru->cmd = MEGA_MBOXCMD_PASSTHRU64;
5271 } else {
5272 mboxpthru->dataxferaddr = scb->dma_passthruhandle64;
5273 pthru->dataxferaddr =
5274 pci_map_single (megacfg->dev,
5275 ioc->data,
5276 4096, PCI_DMA_BIDIRECTIONAL);
5277 pthru->numsgelements = 0;
5278 }
5279
5280#else
5281 {
5282 mboxpthru->dataxferaddr = virt_to_bus (&scb->pthru);
5283 pthru->dataxferaddr = virt_to_bus (ioc->data);
5284 pthru->numsgelements = 0;
5285 }
5286#endif
5287
5288 pthru->reqsenselen = 14;
5289 break;
5290
5291 default:
5292 mboxioc = (mega_ioctl_mbox *) scb->mboxData;
5293
5294 if (ioc->ui.fcs.opcode == M_RD_IOCTL_CMD_NEW) {
5295 scb->buff_ptr = ioc->ui.fcs.buffer;
5296 scb->iDataSize = ioc->ui.fcs.length;
5297 } else {
5298 scb->buff_ptr = ioc->data;
5299 scb->iDataSize = 4096;
5300 }
5301
5302 set_mbox_xfer_addr (megacfg, scb, mboxioc, FROMTO_DEVICE);
5303 mboxioc->numsgelements = 0;
5304 break;
5305 }
5306
5307 return scb;
5308}
5309
5310static int
5311megadev_close (struct inode *inode, struct file *filep)
5312{
5313#ifdef MODULE
5314 MOD_DEC_USE_COUNT;
5315#endif
5316 return 0;
5317}
5318
5319
5320static int
5321mega_support_ext_cdb(mega_host_config *this_hba)
5322{
5323 mega_mailbox *mboxpnt;
5324 unsigned char mbox[16];
5325 int ret;
5326
5327 mboxpnt = (mega_mailbox *) mbox;
5328
5329 memset(mbox, 0, sizeof (mbox));
5330
5331
5332
5333 mbox[0] = 0xA4;
5334 mbox[2] = 0x16;
5335
5336 ret = megaIssueCmd(this_hba, mbox, NULL, 0);
5337
5338 return !ret;
5339}
5340
5341
5342
5343
5344
5345
5346static int
5347mega_support_random_del(mega_host_config *this_hba)
5348{
5349 mega_mailbox *mboxpnt;
5350 unsigned char mbox[16];
5351 int ret;
5352
5353 mboxpnt = (mega_mailbox *)mbox;
5354
5355 memset(mbox, 0, sizeof(mbox));
5356
5357
5358
5359
5360 mbox[0] = FC_DEL_LOGDRV;
5361 mbox[2] = OP_SUP_DEL_LOGDRV;
5362
5363 ret = megaIssueCmd(this_hba, mbox, NULL, 0);
5364
5365 return !ret;
5366}
5367
5368static int
5369mega_del_logdrv(mega_host_config *this_hba, int logdrv)
5370{
5371 int rval;
5372 IO_LOCK_T;
5373 DECLARE_WAIT_QUEUE_HEAD(wq);
5374 mega_scb *scbp;
5375
5376
5377
5378
5379
5380 IO_LOCK;
5381 this_hba->quiescent = 1;
5382 IO_UNLOCK;
5383
5384 while( this_hba->qPcnt ) {
5385 sleep_on_timeout( &wq, 1*HZ );
5386 }
5387 rval = mega_do_del_logdrv(this_hba, logdrv);
5388
5389 IO_LOCK;
5390
5391
5392
5393 if( this_hba->qPendingH == NULL ) {
5394
5395
5396
5397
5398 this_hba->qPendingH = this_hba->int_qh;
5399 this_hba->qPendingT = this_hba->int_qt;
5400 this_hba->qPcnt = this_hba->int_qlen;
5401 }
5402 else {
5403
5404
5405
5406 if( this_hba->int_qt ) {
5407 this_hba->int_qt->next = this_hba->qPendingH;
5408
5409 this_hba->qPendingH = this_hba->int_qh;
5410 this_hba->qPcnt += this_hba->int_qlen;
5411 }
5412 }
5413
5414 this_hba->int_qh = this_hba->int_qt = NULL;
5415 this_hba->int_qlen = 0;
5416
5417
5418
5419
5420
5421 if( this_hba->read_ldidmap) {
5422 for( scbp = this_hba->qPendingH; scbp; scbp = scbp->next ) {
5423#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5424 if( scbp->pthru->logdrv < 0x80 )
5425 scbp->pthru->logdrv += 0x80;
5426#else
5427 if( scbp->pthru.logdrv < 0x80 )
5428 scbp->pthru.logdrv += 0x80;
5429#endif
5430 }
5431 }
5432 this_hba->quiescent = 0;
5433
5434 IO_UNLOCK;
5435
5436 return rval;
5437}
5438
5439
5440static int
5441mega_do_del_logdrv(mega_host_config *this_hba, int logdrv)
5442{
5443 mega_mailbox *mboxpnt;
5444 unsigned char mbox[16];
5445 int rval;
5446
5447 mboxpnt = (mega_mailbox *)mbox;
5448
5449 memset(mbox, 0, sizeof(mbox));
5450
5451 mbox[0] = FC_DEL_LOGDRV;
5452 mbox[2] = OP_DEL_LOGDRV;
5453 mbox[3] = logdrv;
5454
5455 rval = megaIssueCmd(this_hba, mbox, NULL, 0);
5456
5457
5458 if( rval != 0 ) {
5459 printk("megaraid: Attempt to delete logical drive %d failed.",
5460 logdrv);
5461 return rval;
5462 }
5463
5464
5465
5466
5467
5468 this_hba->read_ldidmap = 1;
5469
5470 return rval;
5471}
5472
5473#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
5474void *
5475dma_alloc_consistent(void *dev, size_t size, dma_addr_t *dma_addr)
5476{
5477 void *_tv;
5478 int npages;
5479 int order = 0;
5480
5481
5482
5483
5484 npages = size / PAGE_SIZE;
5485
5486
5487 if(size % PAGE_SIZE)
5488 npages++;
5489
5490 order = mega_get_order(npages);
5491
5492 _tv = (void *)__get_free_pages(GFP_DMA, order);
5493
5494 if( _tv != NULL ) {
5495 memset(_tv, 0, size);
5496 *(dma_addr) = virt_to_bus(_tv);
5497 }
5498
5499 return _tv;
5500}
5501
5502
5503
5504
5505
5506
5507
5508int
5509mega_get_order(int n)
5510{
5511 int i = 0;
5512
5513 while( pow_2(i++) < n )
5514 ;
5515
5516 return i-1;
5517}
5518
5519
5520
5521
5522
5523
5524int
5525pow_2(int i)
5526{
5527 unsigned int v = 1;
5528
5529 while(i--)
5530 v <<= 1;
5531
5532 return v;
5533}
5534
5535void
5536dma_free_consistent(void *dev, size_t size, void *vaddr, dma_addr_t dma_addr)
5537{
5538 int npages;
5539 int order = 0;
5540
5541 npages = size / PAGE_SIZE;
5542
5543 if(size % PAGE_SIZE)
5544 npages++;
5545
5546 if (npages == 1)
5547 order = 0;
5548 else if (npages == 2)
5549 order = 1;
5550 else if (npages <= 4)
5551 order = 2;
5552 else
5553 order = 3;
5554
5555 free_pages((unsigned long)vaddr, order);
5556
5557}
5558#endif
5559
5560#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5561static
5562#endif
5563#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) || defined(MODULE)
5564Scsi_Host_Template driver_template = MEGARAID;
5565
5566#include "scsi_module.c"
5567#endif
5568
5569
5570