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