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#define GDTH_STATISTICS
374
375#include <linux/module.h>
376
377#include <linux/version.h>
378#include <linux/kernel.h>
379#include <linux/types.h>
380#include <linux/pci.h>
381#include <linux/string.h>
382#include <linux/ctype.h>
383#include <linux/ioport.h>
384#include <linux/delay.h>
385#include <linux/sched.h>
386#include <linux/interrupt.h>
387#include <linux/in.h>
388#include <linux/proc_fs.h>
389#include <linux/time.h>
390#include <linux/timer.h>
391#ifdef GDTH_RTC
392#include <linux/mc146818rtc.h>
393#endif
394#include <linux/reboot.h>
395
396#include <asm/dma.h>
397#include <asm/system.h>
398#include <asm/io.h>
399#include <asm/uaccess.h>
400#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
401#include <linux/spinlock.h>
402#else
403#include <asm/spinlock.h>
404#endif
405#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
406#include <linux/blkdev.h>
407#else
408#include <linux/blk.h>
409#include "sd.h"
410#endif
411
412#include "scsi.h"
413#include "hosts.h"
414#include "gdth.h"
415
416static void gdth_delay(int milliseconds);
417static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs);
418#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
419static irqreturn_t gdth_interrupt(int irq, void *dev_id, struct pt_regs *regs);
420#else
421static void gdth_interrupt(int irq, void *dev_id, struct pt_regs *regs);
422#endif
423static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp);
424static int gdth_async_event(int hanum);
425static void gdth_log_event(gdth_evt_data *dvr, char *buffer);
426
427static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority);
428static void gdth_next(int hanum);
429static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b);
430static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp);
431static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source,
432 ushort idx, gdth_evt_data *evt);
433static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr);
434static void gdth_readapp_event(gdth_ha_str *ha, unchar application,
435 gdth_evt_str *estr);
436static void gdth_clear_events(void);
437
438static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
439 char *buffer,ushort count);
440static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp);
441static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive);
442
443static int gdth_search_eisa(ushort eisa_adr);
444static int gdth_search_isa(ulong32 bios_adr);
445static int gdth_search_pci(gdth_pci_str *pcistr);
446static void gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
447 ushort vendor, ushort dev);
448static void gdth_sort_pci(gdth_pci_str *pcistr, int cnt);
449static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha);
450static int gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha);
451static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha);
452
453static void gdth_enable_int(int hanum);
454static int gdth_get_status(unchar *pIStatus,int irq);
455static int gdth_test_busy(int hanum);
456static int gdth_get_cmd_index(int hanum);
457static void gdth_release_event(int hanum);
458static int gdth_wait(int hanum,int index,ulong32 time);
459static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
460 ulong64 p2,ulong64 p3);
461static int gdth_search_drives(int hanum);
462static int gdth_analyse_hdrive(int hanum, ushort hdrive);
463
464static const char *gdth_ctr_name(int hanum);
465
466static int gdth_open(struct inode *inode, struct file *filep);
467static int gdth_close(struct inode *inode, struct file *filep);
468static int gdth_ioctl(struct inode *inode, struct file *filep,
469 unsigned int cmd, unsigned long arg);
470
471static void gdth_flush(int hanum);
472static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
473
474#ifdef DEBUG_GDTH
475static unchar DebugState = DEBUG_GDTH;
476
477#ifdef __SERIAL__
478#define MAX_SERBUF 160
479static void ser_init(void);
480static void ser_puts(char *str);
481static void ser_putc(char c);
482static int ser_printk(const char *fmt, ...);
483static char strbuf[MAX_SERBUF+1];
484#ifdef __COM2__
485#define COM_BASE 0x2f8
486#else
487#define COM_BASE 0x3f8
488#endif
489static void ser_init()
490{
491 unsigned port=COM_BASE;
492
493 outb(0x80,port+3);
494 outb(0,port+1);
495
496 outb(6, port);
497 outb(3,port+3);
498 outb(0,port+1);
499
500
501
502
503}
504
505static void ser_puts(char *str)
506{
507 char *ptr;
508
509 ser_init();
510 for (ptr=str;*ptr;++ptr)
511 ser_putc(*ptr);
512}
513
514static void ser_putc(char c)
515{
516 unsigned port=COM_BASE;
517
518 while ((inb(port+5) & 0x20)==0);
519 outb(c,port);
520 if (c==0x0a)
521 {
522 while ((inb(port+5) & 0x20)==0);
523 outb(0x0d,port);
524 }
525}
526
527static int ser_printk(const char *fmt, ...)
528{
529 va_list args;
530 int i;
531
532 va_start(args,fmt);
533 i = vsprintf(strbuf,fmt,args);
534 ser_puts(strbuf);
535 va_end(args);
536 return i;
537}
538
539#define TRACE(a) {if (DebugState==1) {ser_printk a;}}
540#define TRACE2(a) {if (DebugState==1 || DebugState==2) {ser_printk a;}}
541#define TRACE3(a) {if (DebugState!=0) {ser_printk a;}}
542
543#else
544#define TRACE(a) {if (DebugState==1) {printk a;}}
545#define TRACE2(a) {if (DebugState==1 || DebugState==2) {printk a;}}
546#define TRACE3(a) {if (DebugState!=0) {printk a;}}
547#endif
548
549#else
550#define TRACE(a)
551#define TRACE2(a)
552#define TRACE3(a)
553#endif
554
555#ifdef GDTH_STATISTICS
556static ulong32 max_rq=0, max_index=0, max_sg=0;
557#ifdef INT_COAL
558static ulong32 max_int_coal=0;
559#endif
560static ulong32 act_ints=0, act_ios=0, act_stats=0, act_rq=0;
561static struct timer_list gdth_timer;
562#endif
563
564#define PTR2USHORT(a) (ushort)(ulong)(a)
565#define GDTOFFSOF(a,b) (size_t)&(((a*)0)->b)
566#define INDEX_OK(i,t) ((i)<sizeof(t)/sizeof((t)[0]))
567
568#define NUMDATA(a) ( (gdth_num_str *)((a)->hostdata))
569#define HADATA(a) (&((gdth_ext_str *)((a)->hostdata))->haext)
570#define CMDDATA(a) (&((gdth_ext_str *)((a)->hostdata))->cmdext)
571
572#define BUS_L2P(a,b) ((b)>(a)->virt_bus ? (b-1):(b))
573
574#define gdth_readb(addr) readb((ulong)(addr))
575#define gdth_readw(addr) readw((ulong)(addr))
576#define gdth_readl(addr) (ulong32)readl((ulong)(addr))
577#define gdth_writeb(b,addr) writeb((b),(ulong)(addr))
578#define gdth_writew(b,addr) writew((b),(ulong)(addr))
579#define gdth_writel(b,addr) writel((ulong32)(b),(ulong)(addr))
580
581static unchar gdth_drq_tab[4] = {5,6,7,7};
582static unchar gdth_irq_tab[6] = {0,10,11,12,14,0};
583static unchar gdth_polling;
584static unchar gdth_from_wait = FALSE;
585static int wait_index,wait_hanum;
586static int gdth_ctr_count = 0;
587static int gdth_ctr_vcount = 0;
588static int gdth_ctr_released = 0;
589static struct Scsi_Host *gdth_ctr_tab[MAXHA];
590static struct Scsi_Host *gdth_ctr_vtab[MAXHA*MAXBUS];
591static unchar gdth_write_through = FALSE;
592static gdth_evt_str ebuffer[MAX_EVENTS];
593static int elastidx;
594static int eoldidx;
595static int major;
596
597#define DIN 1
598#define DOU 2
599#define DNO DIN
600#define DUN DIN
601static unchar gdth_direction_tab[0x100] = {
602 DNO,DNO,DIN,DIN,DOU,DIN,DIN,DOU,DIN,DUN,DOU,DOU,DUN,DUN,DUN,DIN,
603 DNO,DIN,DIN,DOU,DIN,DOU,DNO,DNO,DOU,DNO,DIN,DNO,DIN,DOU,DNO,DUN,
604 DIN,DUN,DIN,DUN,DOU,DIN,DUN,DUN,DIN,DIN,DOU,DNO,DUN,DIN,DOU,DOU,
605 DOU,DOU,DOU,DNO,DIN,DNO,DNO,DIN,DOU,DOU,DOU,DOU,DIN,DOU,DIN,DOU,
606 DOU,DOU,DIN,DIN,DIN,DNO,DUN,DNO,DNO,DNO,DUN,DNO,DOU,DIN,DUN,DUN,
607 DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DIN,DUN,DUN,DUN,DUN,DUN,
608 DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
609 DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
610 DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DIN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,
611 DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DIN,DUN,
612 DUN,DUN,DUN,DUN,DUN,DNO,DNO,DUN,DIN,DNO,DOU,DUN,DNO,DUN,DOU,DOU,
613 DOU,DOU,DOU,DNO,DUN,DIN,DOU,DIN,DIN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
614 DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
615 DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
616 DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,
617 DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN
618};
619
620
621#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
622#define __devinitdata
623#endif
624#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
625#define GDTH_INITFUNC(type, func) type __init func
626#include <linux/init.h>
627#else
628#define GDTH_INITFUNC(type, func) __initfunc(type func)
629#include <linux/init.h>
630#endif
631
632#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
633#define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock)
634#define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags)
635#define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags)
636
637#define GDTH_LOCK_SCSI_DONE(dev, flags) spin_lock_irqsave(dev->host_lock,flags)
638#define GDTH_UNLOCK_SCSI_DONE(dev, flags) spin_unlock_irqrestore(dev->host_lock,flags)
639
640#else
641#define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock)
642#define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags)
643#define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags)
644
645#define GDTH_LOCK_SCSI_DONE(flags) spin_lock_irqsave(&io_request_lock,flags)
646#define GDTH_UNLOCK_SCSI_DONE(flags) spin_unlock_irqrestore(&io_request_lock,flags)
647#endif
648
649
650
651static int irq[MAXHA] __initdata =
652{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
653 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
654
655static int disable __initdata = 0;
656
657static int reserve_mode = 1;
658
659static int reserve_list[MAX_RES_ARGS] =
660{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
661 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
662 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
663
664static int reverse_scan = 0;
665
666static int hdr_channel = 0;
667
668static int max_ids = MAXID;
669
670static int rescan = 0;
671
672static int virt_ctr = 0;
673
674static int shared_access = 1;
675
676static int probe_eisa_isa = 0;
677
678static int force_dma32 = 0;
679
680#ifdef MODULE
681
682MODULE_PARM(irq, "i");
683MODULE_PARM(disable, "i");
684MODULE_PARM(reserve_mode, "i");
685MODULE_PARM(reserve_list, "4-" __MODULE_STRING(MAX_RES_ARGS) "i");
686MODULE_PARM(reverse_scan, "i");
687MODULE_PARM(hdr_channel, "i");
688MODULE_PARM(max_ids, "i");
689MODULE_PARM(rescan, "i");
690MODULE_PARM(virt_ctr, "i");
691MODULE_PARM(shared_access, "i");
692MODULE_PARM(probe_eisa_isa, "i");
693MODULE_PARM(force_dma32, "i");
694MODULE_AUTHOR("Achim Leubner");
695#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,11)
696MODULE_LICENSE("GPL");
697#endif
698#endif
699
700
701static struct file_operations gdth_fops = {
702#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
703 .ioctl = gdth_ioctl,
704 .open = gdth_open,
705 .release = gdth_close,
706#else
707 ioctl:gdth_ioctl,
708 open:gdth_open,
709 release:gdth_close,
710#endif
711};
712
713
714#include <linux/stat.h>
715#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
716struct proc_dir_entry proc_scsi_gdth = {
717 PROC_SCSI_GDTH, 4, "gdth",
718 S_IFDIR | S_IRUGO | S_IXUGO, 2
719};
720#endif
721
722#include "gdth_proc.h"
723#include "gdth_proc.c"
724
725
726static struct notifier_block gdth_notifier = {
727 gdth_halt, NULL, 0
728};
729
730
731static void gdth_delay(int milliseconds)
732{
733 if (milliseconds == 0) {
734 udelay(1);
735 } else {
736 mdelay(milliseconds);
737 }
738}
739
740static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs)
741{
742 *cyls = size /HEADS/SECS;
743 if (*cyls <= MAXCYLS) {
744 *heads = HEADS;
745 *secs = SECS;
746 } else {
747 *cyls = size /MEDHEADS/MEDSECS;
748 if (*cyls <= MAXCYLS) {
749 *heads = MEDHEADS;
750 *secs = MEDSECS;
751 } else {
752 *cyls = size /BIGHEADS/BIGSECS;
753 *heads = BIGHEADS;
754 *secs = BIGSECS;
755 }
756 }
757}
758
759
760
761GDTH_INITFUNC(static int, gdth_search_eisa(ushort eisa_adr))
762{
763 ulong32 id;
764
765 TRACE(("gdth_search_eisa() adr. %x\n",eisa_adr));
766 id = inl(eisa_adr+ID0REG);
767 if (id == GDT3A_ID || id == GDT3B_ID) {
768 if ((inb(eisa_adr+EISAREG) & 8) == 0)
769 return 0;
770 return 1;
771 }
772 if (id == GDT3_ID)
773 return 1;
774
775 return 0;
776}
777
778
779GDTH_INITFUNC(static int, gdth_search_isa(ulong32 bios_adr))
780{
781 void *addr;
782 ulong32 id;
783
784 TRACE(("gdth_search_isa() bios adr. %x\n",bios_adr));
785 if ((addr = ioremap(bios_adr+BIOS_ID_OFFS, sizeof(ulong32))) != NULL) {
786 id = gdth_readl(addr);
787 iounmap(addr);
788 if (id == GDT2_ID)
789 return 1;
790 }
791 return 0;
792}
793
794
795GDTH_INITFUNC(static int, gdth_search_pci(gdth_pci_str *pcistr))
796{
797 ushort device, cnt;
798
799 TRACE(("gdth_search_pci()\n"));
800
801 cnt = 0;
802 for (device = 0; device <= PCI_DEVICE_ID_VORTEX_GDT6555; ++device)
803 gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device);
804 for (device = PCI_DEVICE_ID_VORTEX_GDT6x17RP;
805 device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP; ++device)
806 gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device);
807 gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX,
808 PCI_DEVICE_ID_VORTEX_GDTNEWRX);
809 gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX,
810 PCI_DEVICE_ID_VORTEX_GDTNEWRX2);
811 gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
812 PCI_DEVICE_ID_INTEL_SRC);
813 gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
814 PCI_DEVICE_ID_INTEL_SRC_XSCALE);
815 return cnt;
816}
817
818#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
819
820
821
822static struct pci_device_id gdthtable[] __devinitdata = {
823 {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID},
824 {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID},
825 {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID},
826 {0}
827};
828MODULE_DEVICE_TABLE(pci,gdthtable);
829#endif
830
831GDTH_INITFUNC(static void, gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
832 ushort vendor, ushort device))
833{
834 ulong base0, base1, base2;
835 struct pci_dev *pdev;
836
837 TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n",
838 *cnt, vendor, device));
839
840#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
841 pdev = NULL;
842 while ((pdev = pci_find_device(vendor, device, pdev))
843 != NULL) {
844 if (pci_enable_device(pdev))
845 continue;
846 if (*cnt >= MAXHA)
847 return;
848
849 pcistr[*cnt].pdev = pdev;
850 pcistr[*cnt].vendor_id = vendor;
851 pcistr[*cnt].device_id = device;
852 pcistr[*cnt].subdevice_id = pdev->subsystem_device;
853 pcistr[*cnt].bus = pdev->bus->number;
854 pcistr[*cnt].device_fn = pdev->devfn;
855 pcistr[*cnt].irq = pdev->irq;
856 base0 = pci_resource_flags(pdev, 0);
857 base1 = pci_resource_flags(pdev, 1);
858 base2 = pci_resource_flags(pdev, 2);
859 if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B ||
860 device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) {
861 if (!(base0 & IORESOURCE_MEM))
862 continue;
863 pcistr[*cnt].dpmem = pci_resource_start(pdev, 0);
864 } else {
865 if (!(base0 & IORESOURCE_MEM) ||
866 !(base2 & IORESOURCE_MEM) ||
867 !(base1 & IORESOURCE_IO))
868 continue;
869 pcistr[*cnt].dpmem = pci_resource_start(pdev, 2);
870 pcistr[*cnt].io_mm = pci_resource_start(pdev, 0);
871 pcistr[*cnt].io = pci_resource_start(pdev, 1);
872 }
873 TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n",
874 pcistr[*cnt].bus, PCI_SLOT(pcistr[*cnt].device_fn),
875 pcistr[*cnt].irq, pcistr[*cnt].dpmem));
876 (*cnt)++;
877 }
878#else
879 pdev = NULL;
880 while ((pdev = pci_find_device(vendor, device, pdev))
881 != NULL) {
882 if (*cnt >= MAXHA)
883 return;
884
885 pcistr[*cnt].pdev = pdev;
886 pcistr[*cnt].vendor_id = vendor;
887 pcistr[*cnt].device_id = device;
888 pcistr[*cnt].bus = pdev->bus->number;
889 pcistr[*cnt].device_fn = pdev->devfn;
890 pcibios_read_config_word(pcistr[*cnt].bus, pcistr[*cnt].device_fn,
891 PCI_SUBSYSTEM_ID, &pcistr[*cnt].subdevice_id);
892 pcistr[*cnt].irq = pdev->irq;
893 base0 = pdev->base_address[0];
894 base1 = pdev->base_address[1];
895 base2 = pdev->base_address[2];
896 if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B ||
897 device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) {
898 if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
899 PCI_BASE_ADDRESS_SPACE_MEMORY)
900 continue;
901 pcistr[*cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK;
902 } else {
903 if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
904 PCI_BASE_ADDRESS_SPACE_MEMORY ||
905 (base2 & PCI_BASE_ADDRESS_SPACE) !=
906 PCI_BASE_ADDRESS_SPACE_MEMORY ||
907 (base1 & PCI_BASE_ADDRESS_SPACE) !=
908 PCI_BASE_ADDRESS_SPACE_IO)
909 continue;
910 pcistr[*cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK;
911 pcistr[*cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK;
912 pcistr[*cnt].io = base1 & PCI_BASE_ADDRESS_IO_MASK;
913 }
914 TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n",
915 pcistr[*cnt].bus, PCI_SLOT(pcistr[*cnt].device_fn),
916 pcistr[*cnt].irq, pcistr[*cnt].dpmem));
917 (*cnt)++;
918 }
919#endif
920}
921
922
923GDTH_INITFUNC(static void, gdth_sort_pci(gdth_pci_str *pcistr, int cnt))
924{
925 gdth_pci_str temp;
926 int i, changed;
927
928 TRACE(("gdth_sort_pci() cnt %d\n",cnt));
929 if (cnt == 0)
930 return;
931
932 do {
933 changed = FALSE;
934 for (i = 0; i < cnt-1; ++i) {
935 if (!reverse_scan) {
936 if ((pcistr[i].bus > pcistr[i+1].bus) ||
937 (pcistr[i].bus == pcistr[i+1].bus &&
938 PCI_SLOT(pcistr[i].device_fn) >
939 PCI_SLOT(pcistr[i+1].device_fn))) {
940 temp = pcistr[i];
941 pcistr[i] = pcistr[i+1];
942 pcistr[i+1] = temp;
943 changed = TRUE;
944 }
945 } else {
946 if ((pcistr[i].bus < pcistr[i+1].bus) ||
947 (pcistr[i].bus == pcistr[i+1].bus &&
948 PCI_SLOT(pcistr[i].device_fn) <
949 PCI_SLOT(pcistr[i+1].device_fn))) {
950 temp = pcistr[i];
951 pcistr[i] = pcistr[i+1];
952 pcistr[i+1] = temp;
953 changed = TRUE;
954 }
955 }
956 }
957 } while (changed);
958}
959
960
961GDTH_INITFUNC(static int, gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha))
962{
963 ulong32 retries,id;
964 unchar prot_ver,eisacf,i,irq_found;
965
966 TRACE(("gdth_init_eisa() adr. %x\n",eisa_adr));
967
968
969 outb(0xff,eisa_adr+EDOORREG);
970 outb(0x00,eisa_adr+EDENABREG);
971 outb(0x00,eisa_adr+EINTENABREG);
972
973 outb(0xff,eisa_adr+LDOORREG);
974 retries = INIT_RETRIES;
975 gdth_delay(20);
976 while (inb(eisa_adr+EDOORREG) != 0xff) {
977 if (--retries == 0) {
978 printk("GDT-EISA: Initialization error (DEINIT failed)\n");
979 return 0;
980 }
981 gdth_delay(1);
982 TRACE2(("wait for DEINIT: retries=%d\n",retries));
983 }
984 prot_ver = inb(eisa_adr+MAILBOXREG);
985 outb(0xff,eisa_adr+EDOORREG);
986 if (prot_ver != PROTOCOL_VERSION) {
987 printk("GDT-EISA: Illegal protocol version\n");
988 return 0;
989 }
990 ha->bmic = eisa_adr;
991 ha->brd_phys = (ulong32)eisa_adr >> 12;
992
993 outl(0,eisa_adr+MAILBOXREG);
994 outl(0,eisa_adr+MAILBOXREG+4);
995 outl(0,eisa_adr+MAILBOXREG+8);
996 outl(0,eisa_adr+MAILBOXREG+12);
997
998
999 if ((id = inl(eisa_adr+ID0REG)) == GDT3_ID) {
1000 ha->oem_id = OEM_ID_ICP;
1001 ha->type = GDT_EISA;
1002 ha->stype = id;
1003 outl(1,eisa_adr+MAILBOXREG+8);
1004 outb(0xfe,eisa_adr+LDOORREG);
1005 retries = INIT_RETRIES;
1006 gdth_delay(20);
1007 while (inb(eisa_adr+EDOORREG) != 0xfe) {
1008 if (--retries == 0) {
1009 printk("GDT-EISA: Initialization error (get IRQ failed)\n");
1010 return 0;
1011 }
1012 gdth_delay(1);
1013 }
1014 ha->irq = inb(eisa_adr+MAILBOXREG);
1015 outb(0xff,eisa_adr+EDOORREG);
1016 TRACE2(("GDT3000/3020: IRQ=%d\n",ha->irq));
1017
1018 if (ha->irq == 0) {
1019 TRACE2(("Unknown IRQ, use IRQ table from cmd line !\n"));
1020 for (i = 0, irq_found = FALSE;
1021 i < MAXHA && irq[i] != 0xff; ++i) {
1022 if (irq[i]==10 || irq[i]==11 || irq[i]==12 || irq[i]==14) {
1023 irq_found = TRUE;
1024 break;
1025 }
1026 }
1027 if (irq_found) {
1028 ha->irq = irq[i];
1029 irq[i] = 0;
1030 printk("GDT-EISA: Can not detect controller IRQ,\n");
1031 printk("Use IRQ setting from command line (IRQ = %d)\n",
1032 ha->irq);
1033 } else {
1034 printk("GDT-EISA: Initialization error (unknown IRQ), Enable\n");
1035 printk("the controller BIOS or use command line parameters\n");
1036 return 0;
1037 }
1038 }
1039 } else {
1040 eisacf = inb(eisa_adr+EISAREG) & 7;
1041 if (eisacf > 4)
1042 eisacf -= 4;
1043 ha->irq = gdth_irq_tab[eisacf];
1044 ha->oem_id = OEM_ID_ICP;
1045 ha->type = GDT_EISA;
1046 ha->stype = id;
1047 }
1048
1049 ha->dma64_support = 0;
1050 return 1;
1051}
1052
1053
1054GDTH_INITFUNC(static int, gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha))
1055{
1056 register gdt2_dpram_str *dp2_ptr;
1057 int i;
1058 unchar irq_drq,prot_ver;
1059 ulong32 retries;
1060
1061 TRACE(("gdth_init_isa() bios adr. %x\n",bios_adr));
1062
1063 ha->brd = ioremap(bios_adr, sizeof(gdt2_dpram_str));
1064 if (ha->brd == NULL) {
1065 printk("GDT-ISA: Initialization error (DPMEM remap error)\n");
1066 return 0;
1067 }
1068 dp2_ptr = (gdt2_dpram_str *)ha->brd;
1069 gdth_writeb(1, &dp2_ptr->io.memlock);
1070
1071 memset_io((char *)&dp2_ptr->u,0,sizeof(dp2_ptr->u));
1072 if (gdth_readl(&dp2_ptr->u) != 0) {
1073 printk("GDT-ISA: Initialization error (DPMEM write error)\n");
1074 iounmap(ha->brd);
1075 return 0;
1076 }
1077
1078
1079 gdth_writeb(0xff, &dp2_ptr->io.irqdel);
1080 gdth_writeb(0x00, &dp2_ptr->io.irqen);
1081 gdth_writeb(0x00, &dp2_ptr->u.ic.S_Status);
1082 gdth_writeb(0x00, &dp2_ptr->u.ic.Cmd_Index);
1083
1084 irq_drq = gdth_readb(&dp2_ptr->io.rq);
1085 for (i=0; i<3; ++i) {
1086 if ((irq_drq & 1)==0)
1087 break;
1088 irq_drq >>= 1;
1089 }
1090 ha->drq = gdth_drq_tab[i];
1091
1092 irq_drq = gdth_readb(&dp2_ptr->io.rq) >> 3;
1093 for (i=1; i<5; ++i) {
1094 if ((irq_drq & 1)==0)
1095 break;
1096 irq_drq >>= 1;
1097 }
1098 ha->irq = gdth_irq_tab[i];
1099
1100
1101 gdth_writel(bios_adr, &dp2_ptr->u.ic.S_Info[0]);
1102 gdth_writeb(0xff, &dp2_ptr->u.ic.S_Cmd_Indx);
1103 gdth_writeb(0, &dp2_ptr->io.event);
1104 retries = INIT_RETRIES;
1105 gdth_delay(20);
1106 while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xff) {
1107 if (--retries == 0) {
1108 printk("GDT-ISA: Initialization error (DEINIT failed)\n");
1109 iounmap(ha->brd);
1110 return 0;
1111 }
1112 gdth_delay(1);
1113 }
1114 prot_ver = (unchar)gdth_readl(&dp2_ptr->u.ic.S_Info[0]);
1115 gdth_writeb(0, &dp2_ptr->u.ic.Status);
1116 gdth_writeb(0xff, &dp2_ptr->io.irqdel);
1117 if (prot_ver != PROTOCOL_VERSION) {
1118 printk("GDT-ISA: Illegal protocol version\n");
1119 iounmap(ha->brd);
1120 return 0;
1121 }
1122
1123 ha->oem_id = OEM_ID_ICP;
1124 ha->type = GDT_ISA;
1125 ha->ic_all_size = sizeof(dp2_ptr->u);
1126 ha->stype= GDT2_ID;
1127 ha->brd_phys = bios_adr >> 4;
1128
1129
1130 gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[0]);
1131 gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[1]);
1132 gdth_writel(0x01, &dp2_ptr->u.ic.S_Info[2]);
1133 gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[3]);
1134 gdth_writeb(0xfe, &dp2_ptr->u.ic.S_Cmd_Indx);
1135 gdth_writeb(0, &dp2_ptr->io.event);
1136 retries = INIT_RETRIES;
1137 gdth_delay(20);
1138 while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xfe) {
1139 if (--retries == 0) {
1140 printk("GDT-ISA: Initialization error\n");
1141 iounmap(ha->brd);
1142 return 0;
1143 }
1144 gdth_delay(1);
1145 }
1146 gdth_writeb(0, &dp2_ptr->u.ic.Status);
1147 gdth_writeb(0xff, &dp2_ptr->io.irqdel);
1148
1149 ha->dma64_support = 0;
1150 return 1;
1151}
1152
1153
1154GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
1155{
1156 register gdt6_dpram_str *dp6_ptr;
1157 register gdt6c_dpram_str *dp6c_ptr;
1158 register gdt6m_dpram_str *dp6m_ptr;
1159 ulong32 retries;
1160 unchar prot_ver;
1161 ushort command;
1162 int i, found = FALSE;
1163
1164 TRACE(("gdth_init_pci()\n"));
1165
1166 if (pcistr->vendor_id == PCI_VENDOR_ID_INTEL)
1167 ha->oem_id = OEM_ID_INTEL;
1168 else
1169 ha->oem_id = OEM_ID_ICP;
1170 ha->brd_phys = (pcistr->bus << 8) | (pcistr->device_fn & 0xf8);
1171 ha->stype = (ulong32)pcistr->device_id;
1172 ha->subdevice_id = pcistr->subdevice_id;
1173 ha->irq = pcistr->irq;
1174#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1175 ha->pdev = pcistr->pdev;
1176#endif
1177
1178 if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) {
1179 TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
1180 ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6_dpram_str));
1181 if (ha->brd == NULL) {
1182 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1183 return 0;
1184 }
1185
1186 dp6_ptr = (gdt6_dpram_str *)ha->brd;
1187 gdth_writel(DPMEM_MAGIC, &dp6_ptr->u);
1188 if (gdth_readl(&dp6_ptr->u) != DPMEM_MAGIC) {
1189 printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n",
1190 pcistr->dpmem);
1191 found = FALSE;
1192 for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
1193 iounmap(ha->brd);
1194 ha->brd = ioremap(i, sizeof(ushort));
1195 if (ha->brd == NULL) {
1196 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1197 return 0;
1198 }
1199 if (gdth_readw(ha->brd) != 0xffff) {
1200 TRACE2(("init_pci_old() address 0x%x busy\n", i));
1201 continue;
1202 }
1203 iounmap(ha->brd);
1204 pci_write_config_dword(pcistr->pdev,
1205 PCI_BASE_ADDRESS_0, i);
1206 ha->brd = ioremap(i, sizeof(gdt6_dpram_str));
1207 if (ha->brd == NULL) {
1208 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1209 return 0;
1210 }
1211 dp6_ptr = (gdt6_dpram_str *)ha->brd;
1212 gdth_writel(DPMEM_MAGIC, &dp6_ptr->u);
1213 if (gdth_readl(&dp6_ptr->u) == DPMEM_MAGIC) {
1214 printk("GDT-PCI: Use free address at 0x%x\n", i);
1215 found = TRUE;
1216 break;
1217 }
1218 }
1219 if (!found) {
1220 printk("GDT-PCI: No free address found!\n");
1221 iounmap(ha->brd);
1222 return 0;
1223 }
1224 }
1225 memset_io((char *)&dp6_ptr->u,0,sizeof(dp6_ptr->u));
1226 if (gdth_readl(&dp6_ptr->u) != 0) {
1227 printk("GDT-PCI: Initialization error (DPMEM write error)\n");
1228 iounmap(ha->brd);
1229 return 0;
1230 }
1231
1232
1233 gdth_writeb(0xff, &dp6_ptr->io.irqdel);
1234 gdth_writeb(0x00, &dp6_ptr->io.irqen);
1235 gdth_writeb(0x00, &dp6_ptr->u.ic.S_Status);
1236 gdth_writeb(0x00, &dp6_ptr->u.ic.Cmd_Index);
1237
1238 gdth_writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]);
1239 gdth_writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx);
1240 gdth_writeb(0, &dp6_ptr->io.event);
1241 retries = INIT_RETRIES;
1242 gdth_delay(20);
1243 while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xff) {
1244 if (--retries == 0) {
1245 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
1246 iounmap(ha->brd);
1247 return 0;
1248 }
1249 gdth_delay(1);
1250 }
1251 prot_ver = (unchar)gdth_readl(&dp6_ptr->u.ic.S_Info[0]);
1252 gdth_writeb(0, &dp6_ptr->u.ic.S_Status);
1253 gdth_writeb(0xff, &dp6_ptr->io.irqdel);
1254 if (prot_ver != PROTOCOL_VERSION) {
1255 printk("GDT-PCI: Illegal protocol version\n");
1256 iounmap(ha->brd);
1257 return 0;
1258 }
1259
1260 ha->type = GDT_PCI;
1261 ha->ic_all_size = sizeof(dp6_ptr->u);
1262
1263
1264 gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[0]);
1265 gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[1]);
1266 gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[2]);
1267 gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[3]);
1268 gdth_writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx);
1269 gdth_writeb(0, &dp6_ptr->io.event);
1270 retries = INIT_RETRIES;
1271 gdth_delay(20);
1272 while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xfe) {
1273 if (--retries == 0) {
1274 printk("GDT-PCI: Initialization error\n");
1275 iounmap(ha->brd);
1276 return 0;
1277 }
1278 gdth_delay(1);
1279 }
1280 gdth_writeb(0, &dp6_ptr->u.ic.S_Status);
1281 gdth_writeb(0xff, &dp6_ptr->io.irqdel);
1282
1283 ha->dma64_support = 0;
1284
1285 } else if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6555) {
1286 ha->plx = (gdt6c_plx_regs *)pcistr->io;
1287 TRACE2(("init_pci_new() dpmem %lx irq %d\n",
1288 pcistr->dpmem,ha->irq));
1289 ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6c_dpram_str));
1290 if (ha->brd == NULL) {
1291 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1292 iounmap(ha->brd);
1293 return 0;
1294 }
1295
1296 dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
1297 gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u);
1298 if (gdth_readl(&dp6c_ptr->u) != DPMEM_MAGIC) {
1299 printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n",
1300 pcistr->dpmem);
1301 found = FALSE;
1302 for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
1303 iounmap(ha->brd);
1304 ha->brd = ioremap(i, sizeof(ushort));
1305 if (ha->brd == NULL) {
1306 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1307 return 0;
1308 }
1309 if (gdth_readw(ha->brd) != 0xffff) {
1310 TRACE2(("init_pci_plx() address 0x%x busy\n", i));
1311 continue;
1312 }
1313 iounmap(ha->brd);
1314 pci_write_config_dword(pcistr->pdev,
1315 PCI_BASE_ADDRESS_2, i);
1316 ha->brd = ioremap(i, sizeof(gdt6c_dpram_str));
1317 if (ha->brd == NULL) {
1318 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1319 return 0;
1320 }
1321 dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
1322 gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u);
1323 if (gdth_readl(&dp6c_ptr->u) == DPMEM_MAGIC) {
1324 printk("GDT-PCI: Use free address at 0x%x\n", i);
1325 found = TRUE;
1326 break;
1327 }
1328 }
1329 if (!found) {
1330 printk("GDT-PCI: No free address found!\n");
1331 iounmap(ha->brd);
1332 return 0;
1333 }
1334 }
1335 memset_io((char *)&dp6c_ptr->u,0,sizeof(dp6c_ptr->u));
1336 if (gdth_readl(&dp6c_ptr->u) != 0) {
1337 printk("GDT-PCI: Initialization error (DPMEM write error)\n");
1338 iounmap(ha->brd);
1339 return 0;
1340 }
1341
1342
1343 outb(0x00,PTR2USHORT(&ha->plx->control1));
1344 outb(0xff,PTR2USHORT(&ha->plx->edoor_reg));
1345
1346 gdth_writeb(0x00, &dp6c_ptr->u.ic.S_Status);
1347 gdth_writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index);
1348
1349 gdth_writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]);
1350 gdth_writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx);
1351
1352 outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
1353
1354 retries = INIT_RETRIES;
1355 gdth_delay(20);
1356 while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xff) {
1357 if (--retries == 0) {
1358 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
1359 iounmap(ha->brd);
1360 return 0;
1361 }
1362 gdth_delay(1);
1363 }
1364 prot_ver = (unchar)gdth_readl(&dp6c_ptr->u.ic.S_Info[0]);
1365 gdth_writeb(0, &dp6c_ptr->u.ic.Status);
1366 if (prot_ver != PROTOCOL_VERSION) {
1367 printk("GDT-PCI: Illegal protocol version\n");
1368 iounmap(ha->brd);
1369 return 0;
1370 }
1371
1372 ha->type = GDT_PCINEW;
1373 ha->ic_all_size = sizeof(dp6c_ptr->u);
1374
1375
1376 gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[0]);
1377 gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[1]);
1378 gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[2]);
1379 gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[3]);
1380 gdth_writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx);
1381
1382 outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
1383
1384 retries = INIT_RETRIES;
1385 gdth_delay(20);
1386 while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) {
1387 if (--retries == 0) {
1388 printk("GDT-PCI: Initialization error\n");
1389 iounmap(ha->brd);
1390 return 0;
1391 }
1392 gdth_delay(1);
1393 }
1394 gdth_writeb(0, &dp6c_ptr->u.ic.S_Status);
1395
1396 ha->dma64_support = 0;
1397
1398 } else {
1399 TRACE2(("init_pci_mpr() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
1400 ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6m_dpram_str));
1401 if (ha->brd == NULL) {
1402 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1403 return 0;
1404 }
1405
1406
1407#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1408 pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command);
1409 command |= 6;
1410 pci_write_config_word(pcistr->pdev, PCI_COMMAND, command);
1411 if (pci_resource_start(pcistr->pdev, 8) == 1UL)
1412 pci_resource_start(pcistr->pdev, 8) = 0UL;
1413 i = 0xFEFF0001UL;
1414 pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, i);
1415 gdth_delay(1);
1416 pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS,
1417 pci_resource_start(pcistr->pdev, 8));
1418#else
1419 pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command);
1420 command |= 6;
1421 pci_write_config_word(pcistr->pdev, PCI_COMMAND, command);
1422 if (pcistr->pdev->rom_address == 1UL)
1423 pcistr->pdev->rom_address = 0UL;
1424 i = 0xFEFF0001UL;
1425 pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, i);
1426 gdth_delay(1);
1427 pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS,
1428 pcistr->pdev->rom_address);
1429#endif
1430
1431
1432
1433 while( ((int)gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg) ) & 3 )
1434 gdth_delay(1);
1435
1436
1437 dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
1438 gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u);
1439 if (gdth_readl(&dp6m_ptr->u) != DPMEM_MAGIC) {
1440 printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n",
1441 pcistr->dpmem);
1442 found = FALSE;
1443 for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
1444 iounmap(ha->brd);
1445 ha->brd = ioremap(i, sizeof(ushort));
1446 if (ha->brd == NULL) {
1447 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1448 return 0;
1449 }
1450 if (gdth_readw(ha->brd) != 0xffff) {
1451 TRACE2(("init_pci_mpr() address 0x%x busy\n", i));
1452 continue;
1453 }
1454 iounmap(ha->brd);
1455 pci_write_config_dword(pcistr->pdev,
1456 PCI_BASE_ADDRESS_0, i);
1457 ha->brd = ioremap(i, sizeof(gdt6m_dpram_str));
1458 if (ha->brd == NULL) {
1459 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1460 return 0;
1461 }
1462 dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
1463 gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u);
1464 if (gdth_readl(&dp6m_ptr->u) == DPMEM_MAGIC) {
1465 printk("GDT-PCI: Use free address at 0x%x\n", i);
1466 found = TRUE;
1467 break;
1468 }
1469 }
1470 if (!found) {
1471 printk("GDT-PCI: No free address found!\n");
1472 iounmap(ha->brd);
1473 return 0;
1474 }
1475 }
1476 memset_io((char *)&dp6m_ptr->u,0,sizeof(dp6m_ptr->u));
1477
1478
1479 gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) | 4,
1480 &dp6m_ptr->i960r.edoor_en_reg);
1481 gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
1482 gdth_writeb(0x00, &dp6m_ptr->u.ic.S_Status);
1483 gdth_writeb(0x00, &dp6m_ptr->u.ic.Cmd_Index);
1484
1485 gdth_writel(pcistr->dpmem, &dp6m_ptr->u.ic.S_Info[0]);
1486 gdth_writeb(0xff, &dp6m_ptr->u.ic.S_Cmd_Indx);
1487 gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg);
1488 retries = INIT_RETRIES;
1489 gdth_delay(20);
1490 while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xff) {
1491 if (--retries == 0) {
1492 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
1493 iounmap(ha->brd);
1494 return 0;
1495 }
1496 gdth_delay(1);
1497 }
1498 prot_ver = (unchar)gdth_readl(&dp6m_ptr->u.ic.S_Info[0]);
1499 gdth_writeb(0, &dp6m_ptr->u.ic.S_Status);
1500 if (prot_ver != PROTOCOL_VERSION) {
1501 printk("GDT-PCI: Illegal protocol version\n");
1502 iounmap(ha->brd);
1503 return 0;
1504 }
1505
1506 ha->type = GDT_PCIMPR;
1507 ha->ic_all_size = sizeof(dp6m_ptr->u);
1508
1509
1510 gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[0]);
1511 gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[1]);
1512 gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[2]);
1513 gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[3]);
1514 gdth_writeb(0xfe, &dp6m_ptr->u.ic.S_Cmd_Indx);
1515 gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg);
1516 retries = INIT_RETRIES;
1517 gdth_delay(20);
1518 while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) {
1519 if (--retries == 0) {
1520 printk("GDT-PCI: Initialization error\n");
1521 iounmap(ha->brd);
1522 return 0;
1523 }
1524 gdth_delay(1);
1525 }
1526 gdth_writeb(0, &dp6m_ptr->u.ic.S_Status);
1527
1528
1529 gdth_writeb(0xfd, &dp6m_ptr->u.ic.S_Cmd_Indx);
1530 gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg);
1531 retries = INIT_RETRIES;
1532 gdth_delay(20);
1533 while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfd) {
1534 if (--retries == 0) {
1535 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
1536 iounmap(ha->brd);
1537 return 0;
1538 }
1539 gdth_delay(1);
1540 }
1541 prot_ver = (unchar)(gdth_readl(&dp6m_ptr->u.ic.S_Info[0]) >> 16);
1542 gdth_writeb(0, &dp6m_ptr->u.ic.S_Status);
1543 if (prot_ver < 0x2b)
1544 ha->dma64_support = 0;
1545 else
1546 ha->dma64_support = 1;
1547 }
1548
1549 return 1;
1550}
1551
1552
1553
1554
1555GDTH_INITFUNC(static void, gdth_enable_int(int hanum))
1556{
1557 gdth_ha_str *ha;
1558 ulong flags;
1559 gdt2_dpram_str *dp2_ptr;
1560 gdt6_dpram_str *dp6_ptr;
1561 gdt6m_dpram_str *dp6m_ptr;
1562
1563 TRACE(("gdth_enable_int() hanum %d\n",hanum));
1564 ha = HADATA(gdth_ctr_tab[hanum]);
1565 GDTH_LOCK_HA(ha, flags);
1566
1567 if (ha->type == GDT_EISA) {
1568 outb(0xff, ha->bmic + EDOORREG);
1569 outb(0xff, ha->bmic + EDENABREG);
1570 outb(0x01, ha->bmic + EINTENABREG);
1571 } else if (ha->type == GDT_ISA) {
1572 dp2_ptr = (gdt2_dpram_str *)ha->brd;
1573 gdth_writeb(1, &dp2_ptr->io.irqdel);
1574 gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);
1575 gdth_writeb(1, &dp2_ptr->io.irqen);
1576 } else if (ha->type == GDT_PCI) {
1577 dp6_ptr = (gdt6_dpram_str *)ha->brd;
1578 gdth_writeb(1, &dp6_ptr->io.irqdel);
1579 gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index);
1580 gdth_writeb(1, &dp6_ptr->io.irqen);
1581 } else if (ha->type == GDT_PCINEW) {
1582 outb(0xff, PTR2USHORT(&ha->plx->edoor_reg));
1583 outb(0x03, PTR2USHORT(&ha->plx->control1));
1584 } else if (ha->type == GDT_PCIMPR) {
1585 dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
1586 gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
1587 gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4,
1588 &dp6m_ptr->i960r.edoor_en_reg);
1589 }
1590 GDTH_UNLOCK_HA(ha, flags);
1591}
1592
1593
1594static int gdth_get_status(unchar *pIStatus,int irq)
1595{
1596 register gdth_ha_str *ha;
1597 int i;
1598
1599 TRACE(("gdth_get_status() irq %d ctr_count %d\n",
1600 irq,gdth_ctr_count));
1601
1602 *pIStatus = 0;
1603 for (i=0; i<gdth_ctr_count; ++i) {
1604 ha = HADATA(gdth_ctr_tab[i]);
1605 if (ha->irq != (unchar)irq)
1606 continue;
1607 if (ha->type == GDT_EISA)
1608 *pIStatus = inb((ushort)ha->bmic + EDOORREG);
1609 else if (ha->type == GDT_ISA)
1610 *pIStatus =
1611 gdth_readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Cmd_Index);
1612 else if (ha->type == GDT_PCI)
1613 *pIStatus =
1614 gdth_readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Cmd_Index);
1615 else if (ha->type == GDT_PCINEW)
1616 *pIStatus = inb(PTR2USHORT(&ha->plx->edoor_reg));
1617 else if (ha->type == GDT_PCIMPR)
1618 *pIStatus =
1619 gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.edoor_reg);
1620
1621 if (*pIStatus)
1622 return i;
1623 }
1624 return -1;
1625}
1626
1627
1628static int gdth_test_busy(int hanum)
1629{
1630 register gdth_ha_str *ha;
1631 register int gdtsema0 = 0;
1632
1633 TRACE(("gdth_test_busy() hanum %d\n",hanum));
1634
1635 ha = HADATA(gdth_ctr_tab[hanum]);
1636 if (ha->type == GDT_EISA)
1637 gdtsema0 = (int)inb(ha->bmic + SEMA0REG);
1638 else if (ha->type == GDT_ISA)
1639 gdtsema0 = (int)gdth_readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
1640 else if (ha->type == GDT_PCI)
1641 gdtsema0 = (int)gdth_readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
1642 else if (ha->type == GDT_PCINEW)
1643 gdtsema0 = (int)inb(PTR2USHORT(&ha->plx->sema0_reg));
1644 else if (ha->type == GDT_PCIMPR)
1645 gdtsema0 =
1646 (int)gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
1647
1648 return (gdtsema0 & 1);
1649}
1650
1651
1652static int gdth_get_cmd_index(int hanum)
1653{
1654 register gdth_ha_str *ha;
1655 int i;
1656
1657 TRACE(("gdth_get_cmd_index() hanum %d\n",hanum));
1658
1659 ha = HADATA(gdth_ctr_tab[hanum]);
1660 for (i=0; i<GDTH_MAXCMDS; ++i) {
1661 if (ha->cmd_tab[i].cmnd == UNUSED_CMND) {
1662 ha->cmd_tab[i].cmnd = ha->pccb->RequestBuffer;
1663 ha->cmd_tab[i].service = ha->pccb->Service;
1664 ha->pccb->CommandIndex = (ulong32)i+2;
1665 return (i+2);
1666 }
1667 }
1668 return 0;
1669}
1670
1671
1672static void gdth_set_sema0(int hanum)
1673{
1674 register gdth_ha_str *ha;
1675
1676 TRACE(("gdth_set_sema0() hanum %d\n",hanum));
1677
1678 ha = HADATA(gdth_ctr_tab[hanum]);
1679 if (ha->type == GDT_EISA) {
1680 outb(1, ha->bmic + SEMA0REG);
1681 } else if (ha->type == GDT_ISA) {
1682 gdth_writeb(1, &((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
1683 } else if (ha->type == GDT_PCI) {
1684 gdth_writeb(1, &((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
1685 } else if (ha->type == GDT_PCINEW) {
1686 outb(1, PTR2USHORT(&ha->plx->sema0_reg));
1687 } else if (ha->type == GDT_PCIMPR) {
1688 gdth_writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
1689 }
1690}
1691
1692
1693static void gdth_copy_command(int hanum)
1694{
1695 register gdth_ha_str *ha;
1696 register gdth_cmd_str *cmd_ptr;
1697 register gdt6m_dpram_str *dp6m_ptr;
1698 register gdt6c_dpram_str *dp6c_ptr;
1699 gdt6_dpram_str *dp6_ptr;
1700 gdt2_dpram_str *dp2_ptr;
1701 ushort cp_count,dp_offset,cmd_no;
1702
1703 TRACE(("gdth_copy_command() hanum %d\n",hanum));
1704
1705 ha = HADATA(gdth_ctr_tab[hanum]);
1706 cp_count = ha->cmd_len;
1707 dp_offset= ha->cmd_offs_dpmem;
1708 cmd_no = ha->cmd_cnt;
1709 cmd_ptr = ha->pccb;
1710
1711 ++ha->cmd_cnt;
1712 if (ha->type == GDT_EISA)
1713 return;
1714
1715
1716 if (cp_count & 3)
1717 cp_count += (4 - (cp_count & 3));
1718
1719 ha->cmd_offs_dpmem += cp_count;
1720
1721
1722 if (ha->type == GDT_ISA) {
1723 dp2_ptr = (gdt2_dpram_str *)ha->brd;
1724 gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET,
1725 &dp2_ptr->u.ic.comm_queue[cmd_no].offset);
1726 gdth_writew((ushort)cmd_ptr->Service,
1727 &dp2_ptr->u.ic.comm_queue[cmd_no].serv_id);
1728 memcpy_toio(&dp2_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
1729 } else if (ha->type == GDT_PCI) {
1730 dp6_ptr = (gdt6_dpram_str *)ha->brd;
1731 gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET,
1732 &dp6_ptr->u.ic.comm_queue[cmd_no].offset);
1733 gdth_writew((ushort)cmd_ptr->Service,
1734 &dp6_ptr->u.ic.comm_queue[cmd_no].serv_id);
1735 memcpy_toio(&dp6_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
1736 } else if (ha->type == GDT_PCINEW) {
1737 dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
1738 gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET,
1739 &dp6c_ptr->u.ic.comm_queue[cmd_no].offset);
1740 gdth_writew((ushort)cmd_ptr->Service,
1741 &dp6c_ptr->u.ic.comm_queue[cmd_no].serv_id);
1742 memcpy_toio(&dp6c_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
1743 } else if (ha->type == GDT_PCIMPR) {
1744 dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
1745 gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET,
1746 &dp6m_ptr->u.ic.comm_queue[cmd_no].offset);
1747 gdth_writew((ushort)cmd_ptr->Service,
1748 &dp6m_ptr->u.ic.comm_queue[cmd_no].serv_id);
1749 memcpy_toio(&dp6m_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
1750 }
1751}
1752
1753
1754static void gdth_release_event(int hanum)
1755{
1756 register gdth_ha_str *ha;
1757
1758 TRACE(("gdth_release_event() hanum %d\n",hanum));
1759 ha = HADATA(gdth_ctr_tab[hanum]);
1760
1761#ifdef GDTH_STATISTICS
1762 {
1763 ulong32 i,j;
1764 for (i=0,j=0; j<GDTH_MAXCMDS; ++j) {
1765 if (ha->cmd_tab[j].cmnd != UNUSED_CMND)
1766 ++i;
1767 }
1768 if (max_index < i) {
1769 max_index = i;
1770 TRACE3(("GDT: max_index = %d\n",(ushort)i));
1771 }
1772 }
1773#endif
1774
1775 if (ha->pccb->OpCode == GDT_INIT)
1776 ha->pccb->Service |= 0x80;
1777
1778 if (ha->type == GDT_EISA) {
1779 if (ha->pccb->OpCode == GDT_INIT)
1780 outl(ha->ccb_phys, ha->bmic + MAILBOXREG);
1781 outb(ha->pccb->Service, ha->bmic + LDOORREG);
1782 } else if (ha->type == GDT_ISA) {
1783 gdth_writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event);
1784 } else if (ha->type == GDT_PCI) {
1785 gdth_writeb(0, &((gdt6_dpram_str *)ha->brd)->io.event);
1786 } else if (ha->type == GDT_PCINEW) {
1787 outb(1, PTR2USHORT(&ha->plx->ldoor_reg));
1788 } else if (ha->type == GDT_PCIMPR) {
1789 gdth_writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.ldoor_reg);
1790 }
1791}
1792
1793
1794static int gdth_wait(int hanum,int index,ulong32 time)
1795{
1796 gdth_ha_str *ha;
1797 int answer_found = FALSE;
1798
1799 TRACE(("gdth_wait() hanum %d index %d time %d\n",hanum,index,time));
1800
1801 ha = HADATA(gdth_ctr_tab[hanum]);
1802 if (index == 0)
1803 return 1;
1804
1805 gdth_from_wait = TRUE;
1806 do {
1807 gdth_interrupt((int)ha->irq,ha,NULL);
1808 if (wait_hanum==hanum && wait_index==index) {
1809 answer_found = TRUE;
1810 break;
1811 }
1812 gdth_delay(1);
1813 } while (--time);
1814 gdth_from_wait = FALSE;
1815
1816 while (gdth_test_busy(hanum))
1817 gdth_delay(0);
1818
1819 return (answer_found);
1820}
1821
1822
1823static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
1824 ulong64 p2,ulong64 p3)
1825{
1826 register gdth_ha_str *ha;
1827 register gdth_cmd_str *cmd_ptr;
1828 int retries,index;
1829
1830 TRACE2(("gdth_internal_cmd() service %d opcode %d\n",service,opcode));
1831
1832 ha = HADATA(gdth_ctr_tab[hanum]);
1833 cmd_ptr = ha->pccb;
1834 memset((char*)cmd_ptr,0,sizeof(gdth_cmd_str));
1835
1836
1837 for (retries = INIT_RETRIES;;) {
1838 cmd_ptr->Service = service;
1839 cmd_ptr->RequestBuffer = INTERNAL_CMND;
1840 if (!(index=gdth_get_cmd_index(hanum))) {
1841 TRACE(("GDT: No free command index found\n"));
1842 return 0;
1843 }
1844 gdth_set_sema0(hanum);
1845 cmd_ptr->OpCode = opcode;
1846 cmd_ptr->BoardNode = LOCALBOARD;
1847 if (service == CACHESERVICE) {
1848 if (opcode == GDT_IOCTL) {
1849 cmd_ptr->u.ioctl.subfunc = p1;
1850 cmd_ptr->u.ioctl.channel = (ulong32)p2;
1851 cmd_ptr->u.ioctl.param_size = (ushort)p3;
1852 cmd_ptr->u.ioctl.p_param = ha->scratch_phys;
1853 } else {
1854 if (ha->cache_feat & GDT_64BIT) {
1855 cmd_ptr->u.cache64.DeviceNo = (ushort)p1;
1856 cmd_ptr->u.cache64.BlockNo = p2;
1857 } else {
1858 cmd_ptr->u.cache.DeviceNo = (ushort)p1;
1859 cmd_ptr->u.cache.BlockNo = (ulong32)p2;
1860 }
1861 }
1862 } else if (service == SCSIRAWSERVICE) {
1863 if (ha->raw_feat & GDT_64BIT) {
1864 cmd_ptr->u.raw64.direction = p1;
1865 cmd_ptr->u.raw64.bus = (unchar)p2;
1866 cmd_ptr->u.raw64.target = (unchar)p3;
1867 cmd_ptr->u.raw64.lun = (unchar)(p3 >> 8);
1868 } else {
1869 cmd_ptr->u.raw.direction = p1;
1870 cmd_ptr->u.raw.bus = (unchar)p2;
1871 cmd_ptr->u.raw.target = (unchar)p3;
1872 cmd_ptr->u.raw.lun = (unchar)(p3 >> 8);
1873 }
1874 } else if (service == SCREENSERVICE) {
1875 if (opcode == GDT_REALTIME) {
1876 *(ulong32 *)&cmd_ptr->u.screen.su.data[0] = p1;
1877 *(ulong32 *)&cmd_ptr->u.screen.su.data[4] = (ulong32)p2;
1878 *(ulong32 *)&cmd_ptr->u.screen.su.data[8] = (ulong32)p3;
1879 }
1880 }
1881 ha->cmd_len = sizeof(gdth_cmd_str);
1882 ha->cmd_offs_dpmem = 0;
1883 ha->cmd_cnt = 0;
1884 gdth_copy_command(hanum);
1885 gdth_release_event(hanum);
1886 gdth_delay(20);
1887 if (!gdth_wait(hanum,index,INIT_TIMEOUT)) {
1888 printk("GDT: Initialization error (timeout service %d)\n",service);
1889 return 0;
1890 }
1891 if (ha->status != S_BSY || --retries == 0)
1892 break;
1893 gdth_delay(1);
1894 }
1895
1896 return (ha->status != S_OK ? 0:1);
1897}
1898
1899
1900
1901
1902GDTH_INITFUNC(static int, gdth_search_drives(int hanum))
1903{
1904 register gdth_ha_str *ha;
1905 ushort cdev_cnt, i;
1906 int ok;
1907 ulong32 bus_no, drv_cnt, drv_no, j;
1908 gdth_getch_str *chn;
1909 gdth_drlist_str *drl;
1910 gdth_iochan_str *ioc;
1911 gdth_raw_iochan_str *iocr;
1912 gdth_arcdl_str *alst;
1913 gdth_alist_str *alst2;
1914 gdth_oem_str_ioctl *oemstr;
1915#ifdef INT_COAL
1916 gdth_perf_modes *pmod;
1917#endif
1918
1919#ifdef GDTH_RTC
1920 unchar rtc[12];
1921 ulong flags;
1922#endif
1923
1924 TRACE(("gdth_search_drives() hanum %d\n",hanum));
1925 ha = HADATA(gdth_ctr_tab[hanum]);
1926 ok = 0;
1927
1928
1929 ha->screen_feat = 0;
1930 if (!force_dma32) {
1931 ok = gdth_internal_cmd(hanum,SCREENSERVICE,GDT_X_INIT_SCR,0,0,0);
1932 if (ok)
1933 ha->screen_feat = GDT_64BIT;
1934 }
1935 if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC))
1936 ok = gdth_internal_cmd(hanum,SCREENSERVICE,GDT_INIT,0,0,0);
1937 if (!ok) {
1938 printk("GDT-HA %d: Initialization error screen service (code %d)\n",
1939 hanum, ha->status);
1940 return 0;
1941 }
1942 TRACE2(("gdth_search_drives(): SCREENSERVICE initialized\n"));
1943
1944#ifdef GDTH_RTC
1945
1946
1947 spin_lock_irqsave(&rtc_lock, flags);
1948 for (j = 0; j < 1000000; ++j)
1949 if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
1950 break;
1951 for (j = 0; j < 1000000; ++j)
1952 if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
1953 break;
1954
1955 do {
1956 for (j = 0; j < 12; ++j)
1957 rtc[j] = CMOS_READ(j);
1958 } while (rtc[0] != CMOS_READ(0));
1959 spin_lock_irqrestore(&rtc_lock, flags);
1960 TRACE2(("gdth_search_drives(): RTC: %x/%x/%x\n",*(ulong32 *)&rtc[0],
1961 *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8]));
1962
1963 gdth_internal_cmd(hanum,SCREENSERVICE,GDT_REALTIME, *(ulong32 *)&rtc[0],
1964 *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8]);
1965#endif
1966
1967
1968 gdth_internal_cmd(hanum,CACHESERVICE,GDT_UNFREEZE_IO,0,0,0);
1969
1970
1971 ha->cache_feat = 0;
1972 if (!force_dma32) {
1973 ok = gdth_internal_cmd(hanum,CACHESERVICE,GDT_X_INIT_HOST,LINUX_OS,0,0);
1974 if (ok)
1975 ha->cache_feat = GDT_64BIT;
1976 }
1977 if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC))
1978 ok = gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0);
1979 if (!ok) {
1980 printk("GDT-HA %d: Initialization error cache service (code %d)\n",
1981 hanum, ha->status);
1982 return 0;
1983 }
1984 TRACE2(("gdth_search_drives(): CACHESERVICE initialized\n"));
1985 cdev_cnt = (ushort)ha->info;
1986 ha->fw_vers = ha->service;
1987
1988#ifdef INT_COAL
1989 if (ha->type == GDT_PCIMPR) {
1990
1991 pmod = (gdth_perf_modes *)ha->pscratch;
1992 pmod->version = 1;
1993 pmod->st_mode = 1;
1994 *((ulong64 *)&pmod->st_buff_addr1) = ha->coal_stat_phys;
1995 pmod->st_buff_indx1 = COALINDEX;
1996 pmod->st_buff_addr2 = 0;
1997 pmod->st_buff_u_addr2 = 0;
1998 pmod->st_buff_indx2 = 0;
1999 pmod->st_buff_size = sizeof(gdth_coal_status) * MAXOFFSETS;
2000 pmod->cmd_mode = 0;
2001 pmod->cmd_buff_addr1 = 0;
2002 pmod->cmd_buff_u_addr1 = 0;
2003 pmod->cmd_buff_indx1 = 0;
2004 pmod->cmd_buff_addr2 = 0;
2005 pmod->cmd_buff_u_addr2 = 0;
2006 pmod->cmd_buff_indx2 = 0;
2007 pmod->cmd_buff_size = 0;
2008 pmod->reserved1 = 0;
2009 pmod->reserved2 = 0;
2010 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,SET_PERF_MODES,
2011 INVALID_CHANNEL,sizeof(gdth_perf_modes))) {
2012 printk("GDT-HA %d: Interrupt coalescing activated\n", hanum);
2013 }
2014 }
2015#endif
2016
2017
2018 iocr = (gdth_raw_iochan_str *)ha->pscratch;
2019 iocr->hdr.version = 0xffffffff;
2020 iocr->hdr.list_entries = MAXBUS;
2021 iocr->hdr.first_chan = 0;
2022 iocr->hdr.last_chan = MAXBUS-1;
2023 iocr->hdr.list_offset = GDTOFFSOF(gdth_raw_iochan_str, list[0]);
2024 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,IOCHAN_RAW_DESC,
2025 INVALID_CHANNEL,sizeof(gdth_raw_iochan_str))) {
2026 TRACE2(("IOCHAN_RAW_DESC supported!\n"));
2027 ha->bus_cnt = iocr->hdr.chan_count;
2028 for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
2029 if (iocr->list[bus_no].proc_id < MAXID)
2030 ha->bus_id[bus_no] = iocr->list[bus_no].proc_id;
2031 else
2032 ha->bus_id[bus_no] = 0xff;
2033 }
2034 } else {
2035
2036 chn = (gdth_getch_str *)ha->pscratch;
2037 for (bus_no = 0; bus_no < MAXBUS; ++bus_no) {
2038 chn->channel_no = bus_no;
2039 if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
2040 SCSI_CHAN_CNT | L_CTRL_PATTERN,
2041 IO_CHANNEL | INVALID_CHANNEL,
2042 sizeof(gdth_getch_str))) {
2043 if (bus_no == 0) {
2044 printk("GDT-HA %d: Error detecting channel count (0x%x)\n",
2045 hanum, ha->status);
2046 return 0;
2047 }
2048 break;
2049 }
2050 if (chn->siop_id < MAXID)
2051 ha->bus_id[bus_no] = chn->siop_id;
2052 else
2053 ha->bus_id[bus_no] = 0xff;
2054 }
2055 ha->bus_cnt = (unchar)bus_no;
2056 }
2057 TRACE2(("gdth_search_drives() %d channels\n",ha->bus_cnt));
2058
2059
2060 if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_INFO,
2061 INVALID_CHANNEL,sizeof(gdth_cinfo_str))) {
2062 printk("GDT-HA %d: Initialization error cache service (code %d)\n",
2063 hanum, ha->status);
2064 return 0;
2065 }
2066 ha->cpar = ((gdth_cinfo_str *)ha->pscratch)->cpar;
2067 TRACE2(("gdth_search_drives() cinfo: vs %x sta %d str %d dw %d b %d\n",
2068 ha->cpar.version,ha->cpar.state,ha->cpar.strategy,
2069 ha->cpar.write_back,ha->cpar.block_size));
2070
2071
2072 ha->more_proc = FALSE;
2073 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_INFO,
2074 INVALID_CHANNEL,sizeof(gdth_binfo_str))) {
2075 memcpy(&ha->binfo, (gdth_binfo_str *)ha->pscratch,
2076 sizeof(gdth_binfo_str));
2077 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_FEATURES,
2078 INVALID_CHANNEL,sizeof(gdth_bfeat_str))) {
2079 TRACE2(("BOARD_INFO/BOARD_FEATURES supported\n"));
2080 ha->bfeat = *(gdth_bfeat_str *)ha->pscratch;
2081 ha->more_proc = TRUE;
2082 }
2083 } else {
2084 TRACE2(("BOARD_INFO requires firmware >= 1.10/2.08\n"));
2085 strcpy(ha->binfo.type_string, gdth_ctr_name(hanum));
2086 }
2087 TRACE2(("Controller name: %s\n",ha->binfo.type_string));
2088
2089
2090 if (ha->more_proc) {
2091
2092 ioc = (gdth_iochan_str *)ha->pscratch;
2093 ioc->hdr.version = 0xffffffff;
2094 ioc->hdr.list_entries = MAXBUS;
2095 ioc->hdr.first_chan = 0;
2096 ioc->hdr.last_chan = MAXBUS-1;
2097 ioc->hdr.list_offset = GDTOFFSOF(gdth_iochan_str, list[0]);
2098 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,IOCHAN_DESC,
2099 INVALID_CHANNEL,sizeof(gdth_iochan_str))) {
2100 for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
2101 ha->raw[bus_no].address = ioc->list[bus_no].address;
2102 ha->raw[bus_no].local_no = ioc->list[bus_no].local_no;
2103 }
2104 } else {
2105 for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
2106 ha->raw[bus_no].address = IO_CHANNEL;
2107 ha->raw[bus_no].local_no = bus_no;
2108 }
2109 }
2110 for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
2111 chn = (gdth_getch_str *)ha->pscratch;
2112 chn->channel_no = ha->raw[bus_no].local_no;
2113 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
2114 SCSI_CHAN_CNT | L_CTRL_PATTERN,
2115 ha->raw[bus_no].address | INVALID_CHANNEL,
2116 sizeof(gdth_getch_str))) {
2117 ha->raw[bus_no].pdev_cnt = chn->drive_cnt;
2118 TRACE2(("Channel %d: %d phys. drives\n",
2119 bus_no,chn->drive_cnt));
2120 }
2121 if (ha->raw[bus_no].pdev_cnt > 0) {
2122 drl = (gdth_drlist_str *)ha->pscratch;
2123 drl->sc_no = ha->raw[bus_no].local_no;
2124 drl->sc_cnt = ha->raw[bus_no].pdev_cnt;
2125 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
2126 SCSI_DR_LIST | L_CTRL_PATTERN,
2127 ha->raw[bus_no].address | INVALID_CHANNEL,
2128 sizeof(gdth_drlist_str))) {
2129 for (j = 0; j < ha->raw[bus_no].pdev_cnt; ++j)
2130 ha->raw[bus_no].id_list[j] = drl->sc_list[j];
2131 } else {
2132 ha->raw[bus_no].pdev_cnt = 0;
2133 }
2134 }
2135 }
2136
2137
2138 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_DRV_CNT,
2139 INVALID_CHANNEL,sizeof(ulong32))) {
2140 drv_cnt = *(ulong32 *)ha->pscratch;
2141 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_DRV_LIST,
2142 INVALID_CHANNEL,drv_cnt * sizeof(ulong32))) {
2143 for (j = 0; j < drv_cnt; ++j) {
2144 drv_no = ((ulong32 *)ha->pscratch)[j];
2145 if (drv_no < MAX_LDRIVES) {
2146 ha->hdr[drv_no].is_logdrv = TRUE;
2147 TRACE2(("Drive %d is log. drive\n",drv_no));
2148 }
2149 }
2150 }
2151 alst = (gdth_arcdl_str *)ha->pscratch;
2152 alst->entries_avail = MAX_LDRIVES;
2153 alst->first_entry = 0;
2154 alst->list_offset = GDTOFFSOF(gdth_arcdl_str, list[0]);
2155 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
2156 ARRAY_DRV_LIST2 | LA_CTRL_PATTERN,
2157 INVALID_CHANNEL, sizeof(gdth_arcdl_str) +
2158 (alst->entries_avail-1) * sizeof(gdth_alist_str))) {
2159 for (j = 0; j < alst->entries_init; ++j) {
2160 ha->hdr[j].is_arraydrv = alst->list[j].is_arrayd;
2161 ha->hdr[j].is_master = alst->list[j].is_master;
2162 ha->hdr[j].is_parity = alst->list[j].is_parity;
2163 ha->hdr[j].is_hotfix = alst->list[j].is_hotfix;
2164 ha->hdr[j].master_no = alst->list[j].cd_handle;
2165 }
2166 } else if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
2167 ARRAY_DRV_LIST | LA_CTRL_PATTERN,
2168 0, 35 * sizeof(gdth_alist_str))) {
2169 for (j = 0; j < 35; ++j) {
2170 alst2 = &((gdth_alist_str *)ha->pscratch)[j];
2171 ha->hdr[j].is_arraydrv = alst2->is_arrayd;
2172 ha->hdr[j].is_master = alst2->is_master;
2173 ha->hdr[j].is_parity = alst2->is_parity;
2174 ha->hdr[j].is_hotfix = alst2->is_hotfix;
2175 ha->hdr[j].master_no = alst2->cd_handle;
2176 }
2177 }
2178 }
2179 }
2180
2181
2182 ha->raw_feat = 0;
2183 if (!force_dma32) {
2184 ok = gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_X_INIT_RAW,0,0,0);
2185 if (ok)
2186 ha->raw_feat = GDT_64BIT;
2187 }
2188 if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC))
2189 ok = gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0);
2190 if (!ok) {
2191 printk("GDT-HA %d: Initialization error raw service (code %d)\n",
2192 hanum, ha->status);
2193 return 0;
2194 }
2195 TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n"));
2196
2197
2198 if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_SET_FEAT,SCATTER_GATHER,
2199 0,0)) {
2200 TRACE2(("gdth_search_drives(): set features RAWSERVICE OK\n"));
2201 if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_GET_FEAT,0,0,0)) {
2202 TRACE2(("gdth_search_dr(): get feat RAWSERVICE %d\n",
2203 ha->info));
2204 ha->raw_feat |= (ushort)ha->info;
2205 }
2206 }
2207
2208
2209 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_SET_FEAT,0,
2210 SCATTER_GATHER,0)) {
2211 TRACE2(("gdth_search_drives(): set features CACHESERVICE OK\n"));
2212 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_GET_FEAT,0,0,0)) {
2213 TRACE2(("gdth_search_dr(): get feat CACHESERV. %d\n",
2214 ha->info));
2215 ha->cache_feat |= (ushort)ha->info;
2216 }
2217 }
2218
2219
2220 if (reserve_mode != 0) {
2221 gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE_ALL,
2222 reserve_mode == 1 ? 1 : 3, 0, 0);
2223 TRACE2(("gdth_search_drives(): RESERVE_ALL code %d\n",
2224 ha->status));
2225 }
2226 for (i = 0; i < MAX_RES_ARGS; i += 4) {
2227 if (reserve_list[i] == hanum && reserve_list[i+1] < ha->bus_cnt &&
2228 reserve_list[i+2] < ha->tid_cnt && reserve_list[i+3] < MAXLUN) {
2229 TRACE2(("gdth_search_drives(): reserve ha %d bus %d id %d lun %d\n",
2230 reserve_list[i], reserve_list[i+1],
2231 reserve_list[i+2], reserve_list[i+3]));
2232 if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE,0,
2233 reserve_list[i+1], reserve_list[i+2] |
2234 (reserve_list[i+3] << 8))) {
2235 printk("GDT-HA %d: Error raw service (RESERVE, code %d)\n",
2236 hanum, ha->status);
2237 }
2238 }
2239 }
2240
2241
2242 oemstr = (gdth_oem_str_ioctl *)ha->pscratch;
2243 oemstr->params.ctl_version = 0x01;
2244 oemstr->params.buffer_size = sizeof(oemstr->text);
2245 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
2246 CACHE_READ_OEM_STRING_RECORD,INVALID_CHANNEL,
2247 sizeof(gdth_oem_str_ioctl))) {
2248 TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD OK\n"));
2249 printk("GDT-HA %d: Vendor: %s Name: %s\n",
2250 hanum,oemstr->text.oem_company_name,ha->binfo.type_string);
2251
2252#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
2253 strlcpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id,
2254 sizeof(ha->oem_name));
2255#else
2256 strncpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id,7);
2257 ha->oem_name[7] = '\0';
2258#endif
2259 } else {
2260
2261 TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD failed\n"));
2262 printk("GDT-HA %d: Name: %s\n",
2263 hanum,ha->binfo.type_string);
2264#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
2265 if (ha->oem_id == OEM_ID_INTEL)
2266 strlcpy(ha->oem_name,"Intel ", sizeof(ha->oem_name));
2267 else
2268 strlcpy(ha->oem_name,"ICP ", sizeof(ha->oem_name));
2269#else
2270 if (ha->oem_id == OEM_ID_INTEL)
2271 strcpy(ha->oem_name,"Intel ");
2272 else
2273 strcpy(ha->oem_name,"ICP ");
2274#endif
2275 }
2276
2277
2278 for (i = 0; i < cdev_cnt; ++i)
2279 gdth_analyse_hdrive(hanum,i);
2280
2281 TRACE(("gdth_search_drives() OK\n"));
2282 return 1;
2283}
2284
2285static int gdth_analyse_hdrive(int hanum,ushort hdrive)
2286{
2287 register gdth_ha_str *ha;
2288 ulong32 drv_cyls;
2289 int drv_hds, drv_secs;
2290
2291 TRACE(("gdth_analyse_hdrive() hanum %d drive %d\n",hanum,hdrive));
2292 if (hdrive >= MAX_HDRIVES)
2293 return 0;
2294 ha = HADATA(gdth_ctr_tab[hanum]);
2295
2296 if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INFO,hdrive,0,0))
2297 return 0;
2298 ha->hdr[hdrive].present = TRUE;
2299 ha->hdr[hdrive].size = ha->info;
2300
2301
2302 ha->hdr[hdrive].size &= ~SECS32;
2303 if (ha->info2 == 0) {
2304 gdth_eval_mapping(ha->hdr[hdrive].size,&drv_cyls,&drv_hds,&drv_secs);
2305 } else {
2306 drv_hds = ha->info2 & 0xff;
2307 drv_secs = (ha->info2 >> 8) & 0xff;
2308 drv_cyls = (ulong32)ha->hdr[hdrive].size / drv_hds / drv_secs;
2309 }
2310 ha->hdr[hdrive].heads = (unchar)drv_hds;
2311 ha->hdr[hdrive].secs = (unchar)drv_secs;
2312
2313 ha->hdr[hdrive].size = drv_cyls * drv_hds * drv_secs;
2314
2315 if (ha->cache_feat & GDT_64BIT) {
2316 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_X_INFO,hdrive,0,0)
2317 && ha->info2 != 0) {
2318 ha->hdr[hdrive].size = ((ulong64)ha->info2 << 32) | ha->info;
2319 }
2320 }
2321 TRACE2(("gdth_search_dr() cdr. %d size %d hds %d scs %d\n",
2322 hdrive,ha->hdr[hdrive].size,drv_hds,drv_secs));
2323
2324
2325 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_DEVTYPE,hdrive,0,0)) {
2326 TRACE2(("gdth_search_dr() cache drive %d devtype %d\n",
2327 hdrive,ha->info));
2328 ha->hdr[hdrive].devtype = (ushort)ha->info;
2329 }
2330
2331
2332 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_CLUST_INFO,hdrive,0,0)) {
2333 TRACE2(("gdth_search_dr() cache drive %d cluster info %d\n",
2334 hdrive,ha->info));
2335 if (!shared_access)
2336 ha->hdr[hdrive].cluster_type = (unchar)ha->info;
2337 }
2338
2339
2340 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_RW_ATTRIBS,hdrive,0,0)) {
2341 TRACE2(("gdth_search_dr() cache drive %d r/w attrib. %d\n",
2342 hdrive,ha->info));
2343 ha->hdr[hdrive].rw_attribs = (unchar)ha->info;
2344 }
2345
2346 return 1;
2347}
2348
2349
2350
2351
2352static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority)
2353{
2354 register gdth_ha_str *ha;
2355 register Scsi_Cmnd *pscp;
2356 register Scsi_Cmnd *nscp;
2357 ulong flags;
2358 unchar b, t;
2359
2360 TRACE(("gdth_putq() priority %d\n",priority));
2361 ha = HADATA(gdth_ctr_tab[hanum]);
2362 GDTH_LOCK_HA(ha, flags);
2363
2364 scp->SCp.this_residual = (int)priority;
2365#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
2366 b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
2367 t = scp->device->id;
2368#else
2369 b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
2370 t = scp->target;
2371#endif
2372 if (priority >= DEFAULT_PRI) {
2373 if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
2374 (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) {
2375 TRACE2(("gdth_putq(): locked IO -> update_timeout()\n"));
2376 scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
2377 }
2378 }
2379
2380 if (ha->req_first==NULL) {
2381 ha->req_first = scp;
2382 scp->SCp.ptr = NULL;
2383 } else {
2384 pscp = ha->req_first;
2385 nscp = (Scsi_Cmnd *)pscp->SCp.ptr;
2386
2387 while (nscp && (unchar)nscp->SCp.this_residual <= priority) {
2388 pscp = nscp;
2389 nscp = (Scsi_Cmnd *)pscp->SCp.ptr;
2390 }
2391 pscp->SCp.ptr = (char *)scp;
2392 scp->SCp.ptr = (char *)nscp;
2393 }
2394 GDTH_UNLOCK_HA(ha, flags);
2395
2396#ifdef GDTH_STATISTICS
2397 flags = 0;
2398 for (nscp=ha->req_first; nscp; nscp=(Scsi_Cmnd*)nscp->SCp.ptr)
2399 ++flags;
2400 if (max_rq < flags) {
2401 max_rq = flags;
2402 TRACE3(("GDT: max_rq = %d\n",(ushort)max_rq));
2403 }
2404#endif
2405}
2406
2407static void gdth_next(int hanum)
2408{
2409 register gdth_ha_str *ha;
2410 register Scsi_Cmnd *pscp;
2411 register Scsi_Cmnd *nscp;
2412 unchar b, t, l, firsttime;
2413 unchar this_cmd, next_cmd;
2414 ulong flags = 0;
2415 int cmd_index;
2416
2417 TRACE(("gdth_next() hanum %d\n",hanum));
2418 ha = HADATA(gdth_ctr_tab[hanum]);
2419 if (!gdth_polling)
2420 GDTH_LOCK_HA(ha, flags);
2421
2422 ha->cmd_cnt = ha->cmd_offs_dpmem = 0;
2423 this_cmd = firsttime = TRUE;
2424 next_cmd = gdth_polling ? FALSE:TRUE;
2425 cmd_index = 0;
2426
2427 for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) {
2428 if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr)
2429 pscp = (Scsi_Cmnd *)pscp->SCp.ptr;
2430#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
2431 b = virt_ctr ? NUMDATA(nscp->device->host)->busnum : nscp->device->channel;
2432 t = nscp->device->id;
2433 l = nscp->device->lun;
2434#else
2435 b = virt_ctr ? NUMDATA(nscp->host)->busnum : nscp->channel;
2436 t = nscp->target;
2437 l = nscp->lun;
2438#endif
2439 if (nscp->SCp.this_residual >= DEFAULT_PRI) {
2440 if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
2441 (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock))
2442 continue;
2443 }
2444
2445 if (firsttime) {
2446 if (gdth_test_busy(hanum)) {
2447 TRACE(("gdth_next() controller %d busy !\n",hanum));
2448 if (!gdth_polling) {
2449 GDTH_UNLOCK_HA(ha, flags);
2450 return;
2451 }
2452 while (gdth_test_busy(hanum))
2453 gdth_delay(1);
2454 }
2455 firsttime = FALSE;
2456 }
2457
2458 if (nscp->done != gdth_scsi_done || nscp->cmnd[0] != 0xff) {
2459 if (nscp->SCp.phase == -1) {
2460 nscp->SCp.phase = CACHESERVICE;
2461 if (nscp->cmnd[0] == TEST_UNIT_READY) {
2462 TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n",
2463 b, t, l));
2464
2465 if ((ha->scan_mode & 0x0f) == 0) {
2466 if (b == 0 && t == 0 && l == 0) {
2467 ha->scan_mode |= 1;
2468 TRACE2(("Scan mode: 0x%x\n", ha->scan_mode));
2469 }
2470 } else if ((ha->scan_mode & 0x0f) == 1) {
2471 if (b == 0 && ((t == 0 && l == 1) ||
2472 (t == 1 && l == 0))) {
2473 nscp->SCp.sent_command = GDT_SCAN_START;
2474 nscp->SCp.phase = ((ha->scan_mode & 0x10 ? 1:0) << 8)
2475 | SCSIRAWSERVICE;
2476 ha->scan_mode = 0x12;
2477 TRACE2(("Scan mode: 0x%x (SCAN_START)\n",
2478 ha->scan_mode));
2479 } else {
2480 ha->scan_mode &= 0x10;
2481 TRACE2(("Scan mode: 0x%x\n", ha->scan_mode));
2482 }
2483 } else if (ha->scan_mode == 0x12) {
2484 if (b == ha->bus_cnt && t == ha->tid_cnt-1) {
2485 nscp->SCp.phase = SCSIRAWSERVICE;
2486 nscp->SCp.sent_command = GDT_SCAN_END;
2487 ha->scan_mode &= 0x10;
2488 TRACE2(("Scan mode: 0x%x (SCAN_END)\n",
2489 ha->scan_mode));
2490 }
2491 }
2492 }
2493 if (b == ha->virt_bus && nscp->cmnd[0] != INQUIRY &&
2494 nscp->cmnd[0] != READ_CAPACITY && nscp->cmnd[0] != MODE_SENSE &&
2495 (ha->hdr[t].cluster_type & CLUSTER_DRIVE)) {
2496
2497 nscp->SCp.sent_command = GDT_CLUST_INFO;
2498 }
2499 }
2500 }
2501
2502 if (nscp->SCp.sent_command != -1) {
2503 if ((nscp->SCp.phase & 0xff) == CACHESERVICE) {
2504 if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
2505 this_cmd = FALSE;
2506 next_cmd = FALSE;
2507 } else if ((nscp->SCp.phase & 0xff) == SCSIRAWSERVICE) {
2508 if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b))))
2509 this_cmd = FALSE;
2510 next_cmd = FALSE;
2511 } else {
2512 memset((char*)nscp->sense_buffer,0,16);
2513 nscp->sense_buffer[0] = 0x70;
2514 nscp->sense_buffer[2] = NOT_READY;
2515 nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
2516 if (!nscp->SCp.have_data_in)
2517 nscp->SCp.have_data_in++;
2518 else {
2519 if (!gdth_polling)
2520 GDTH_UNLOCK_HA(ha,flags);
2521
2522 nscp->scsi_done(nscp);
2523 if (!gdth_polling)
2524 GDTH_LOCK_HA(ha,flags);
2525 }
2526 }
2527 } else if (nscp->done == gdth_scsi_done && nscp->cmnd[0] == 0xff) {
2528 if (!(cmd_index=gdth_special_cmd(hanum,nscp)))
2529 this_cmd = FALSE;
2530 next_cmd = FALSE;
2531 } else if (b != ha->virt_bus) {
2532 if (ha->raw[BUS_L2P(ha,b)].io_cnt[t] >= GDTH_MAX_RAW ||
2533 !(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b))))
2534 this_cmd = FALSE;
2535 else
2536 ha->raw[BUS_L2P(ha,b)].io_cnt[t]++;
2537 } else if (t >= MAX_HDRIVES || !ha->hdr[t].present || l != 0) {
2538 TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n",
2539 nscp->cmnd[0], b, t, l));
2540 nscp->result = DID_BAD_TARGET << 16;
2541 if (!nscp->SCp.have_data_in)
2542 nscp->SCp.have_data_in++;
2543 else {
2544 if (!gdth_polling)
2545 GDTH_UNLOCK_HA(ha,flags);
2546
2547 nscp->scsi_done(nscp);
2548 if (!gdth_polling)
2549 GDTH_LOCK_HA(ha,flags);
2550 }
2551 } else {
2552 switch (nscp->cmnd[0]) {
2553 case TEST_UNIT_READY:
2554 case INQUIRY:
2555 case REQUEST_SENSE:
2556 case READ_CAPACITY:
2557 case VERIFY:
2558 case START_STOP:
2559 case MODE_SENSE:
2560#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
2561 case SERVICE_ACTION_IN:
2562#endif
2563 TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
2564 nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
2565 nscp->cmnd[4],nscp->cmnd[5]));
2566 if (ha->hdr[t].media_changed && nscp->cmnd[0] != INQUIRY) {
2567
2568 TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n",
2569 nscp->cmnd[0], t));
2570 ha->hdr[t].media_changed = FALSE;
2571 memset((char*)nscp->sense_buffer,0,16);
2572 nscp->sense_buffer[0] = 0x70;
2573 nscp->sense_buffer[2] = UNIT_ATTENTION;
2574 nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
2575 if (!nscp->SCp.have_data_in)
2576 nscp->SCp.have_data_in++;
2577 else {
2578 if (!gdth_polling)
2579 GDTH_UNLOCK_HA(ha,flags);
2580
2581 nscp->scsi_done(nscp);
2582 if (!gdth_polling)
2583 GDTH_LOCK_HA(ha,flags);
2584 }
2585 } else if (gdth_internal_cache_cmd(hanum,nscp)) {
2586 if (!gdth_polling)
2587 GDTH_UNLOCK_HA(ha,flags);
2588
2589 nscp->scsi_done(nscp);
2590 if (!gdth_polling)
2591 GDTH_LOCK_HA(ha,flags);
2592 }
2593 break;
2594
2595 case ALLOW_MEDIUM_REMOVAL:
2596 TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
2597 nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
2598 nscp->cmnd[4],nscp->cmnd[5]));
2599 if ( (nscp->cmnd[4]&1) && !(ha->hdr[t].devtype&1) ) {
2600 TRACE(("Prevent r. nonremov. drive->do nothing\n"));
2601 nscp->result = DID_OK << 16;
2602 nscp->sense_buffer[0] = 0;
2603 if (!nscp->SCp.have_data_in)
2604 nscp->SCp.have_data_in++;
2605 else {
2606 if (!gdth_polling)
2607 GDTH_UNLOCK_HA(ha,flags);
2608
2609 nscp->scsi_done(nscp);
2610 if (!gdth_polling)
2611 GDTH_LOCK_HA(ha,flags);
2612 }
2613 } else {
2614 nscp->cmnd[3] = (ha->hdr[t].devtype&1) ? 1:0;
2615 TRACE(("Prevent/allow r. %d rem. drive %d\n",
2616 nscp->cmnd[4],nscp->cmnd[3]));
2617 if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
2618 this_cmd = FALSE;
2619 }
2620 break;
2621
2622 case RESERVE:
2623 case RELEASE:
2624 TRACE2(("cache cmd %s\n",nscp->cmnd[0] == RESERVE ?
2625 "RESERVE" : "RELEASE"));
2626 if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
2627 this_cmd = FALSE;
2628 break;
2629
2630 case READ_6:
2631 case WRITE_6:
2632 case READ_10:
2633 case WRITE_10:
2634#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
2635 case READ_16:
2636 case WRITE_16:
2637#endif
2638 if (ha->hdr[t].media_changed) {
2639
2640 TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n",
2641 nscp->cmnd[0], t));
2642 ha->hdr[t].media_changed = FALSE;
2643 memset((char*)nscp->sense_buffer,0,16);
2644 nscp->sense_buffer[0] = 0x70;
2645 nscp->sense_buffer[2] = UNIT_ATTENTION;
2646 nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
2647 if (!nscp->SCp.have_data_in)
2648 nscp->SCp.have_data_in++;
2649 else {
2650 if (!gdth_polling)
2651 GDTH_UNLOCK_HA(ha,flags);
2652
2653 nscp->scsi_done(nscp);
2654 if (!gdth_polling)
2655 GDTH_LOCK_HA(ha,flags);
2656 }
2657 } else if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
2658 this_cmd = FALSE;
2659 break;
2660
2661 default:
2662 TRACE2(("cache cmd %x/%x/%x/%x/%x/%x unknown\n",nscp->cmnd[0],
2663 nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
2664 nscp->cmnd[4],nscp->cmnd[5]));
2665 printk("GDT-HA %d: Unknown SCSI command 0x%x to cache service !\n",
2666 hanum, nscp->cmnd[0]);
2667 nscp->result = DID_ABORT << 16;
2668 if (!nscp->SCp.have_data_in)
2669 nscp->SCp.have_data_in++;
2670 else {
2671 if (!gdth_polling)
2672 GDTH_UNLOCK_HA(ha,flags);
2673
2674 nscp->scsi_done(nscp);
2675 if (!gdth_polling)
2676 GDTH_LOCK_HA(ha,flags);
2677 }
2678 break;
2679 }
2680 }
2681
2682 if (!this_cmd)
2683 break;
2684 if (nscp == ha->req_first)
2685 ha->req_first = pscp = (Scsi_Cmnd *)nscp->SCp.ptr;
2686 else
2687 pscp->SCp.ptr = nscp->SCp.ptr;
2688 if (!next_cmd)
2689 break;
2690 }
2691
2692 if (ha->cmd_cnt > 0) {
2693 gdth_release_event(hanum);
2694 }
2695
2696 if (!gdth_polling)
2697 GDTH_UNLOCK_HA(ha, flags);
2698
2699 if (gdth_polling && ha->cmd_cnt > 0) {
2700 if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT))
2701 printk("GDT-HA %d: Command %d timed out !\n",
2702 hanum,cmd_index);
2703 }
2704}
2705
2706static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
2707 char *buffer,ushort count)
2708{
2709 ushort cpcount,i;
2710 ushort cpsum,cpnow;
2711 struct scatterlist *sl;
2712 gdth_ha_str *ha;
2713 int sgcnt;
2714 char *address;
2715
2716 cpcount = count<=(ushort)scp->bufflen ? count:(ushort)scp->bufflen;
2717 ha = HADATA(gdth_ctr_tab[hanum]);
2718
2719 if (scp->use_sg) {
2720 sl = (struct scatterlist *)scp->request_buffer;
2721#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
2722 sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,PCI_DMA_FROMDEVICE);
2723 for (i=0,cpsum=0; i<sgcnt; ++i,++sl) {
2724 cpnow = (ushort)sg_dma_len(sl);
2725 TRACE(("copy_internal() now %d sum %d count %d %d\n",
2726 cpnow,cpsum,cpcount,(ushort)scp->bufflen));
2727 if (cpsum+cpnow > cpcount)
2728 cpnow = cpcount - cpsum;
2729 cpsum += cpnow;
2730 if (!sl->page) {
2731 printk("GDT-HA %d: invalid sc/gt element in gdth_copy_internal_data()\n",
2732 hanum);
2733 return;
2734 }
2735 address = (char *)(page_address(sl->page) + sl->offset);
2736 memcpy(address,buffer,cpnow);
2737 if (cpsum == cpcount)
2738 break;
2739 buffer += cpnow;
2740 }
2741 pci_unmap_sg(ha->pdev,scp->request_buffer,
2742 scp->use_sg,PCI_DMA_FROMDEVICE);
2743#else
2744 sgcnt = scp->use_sg;
2745 for (i=0,cpsum=0; i<sgcnt; ++i,++sl) {
2746 cpnow = (ushort)sl->length;
2747 TRACE(("copy_internal() now %d sum %d count %d %d\n",
2748 cpnow,cpsum,cpcount,(ushort)scp->bufflen));
2749 if (cpsum+cpnow > cpcount)
2750 cpnow = cpcount - cpsum;
2751 cpsum += cpnow;
2752 address = (char *)sl->address;
2753 memcpy(address,buffer,cpnow);
2754 if (cpsum == cpcount)
2755 break;
2756 buffer += cpnow;
2757 }
2758#endif
2759 } else {
2760 TRACE(("copy_internal() count %d\n",cpcount));
2761 memcpy((char*)scp->request_buffer,buffer,cpcount);
2762 }
2763}
2764
2765static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
2766{
2767 register gdth_ha_str *ha;
2768 unchar t;
2769 gdth_inq_data inq;
2770 gdth_rdcap_data rdc;
2771 gdth_sense_data sd;
2772 gdth_modep_data mpd;
2773
2774 ha = HADATA(gdth_ctr_tab[hanum]);
2775#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
2776 t = scp->device->id;
2777#else
2778 t = scp->target;
2779#endif
2780 TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n",
2781 scp->cmnd[0],t));
2782
2783 scp->result = DID_OK << 16;
2784 scp->sense_buffer[0] = 0;
2785
2786 switch (scp->cmnd[0]) {
2787 case TEST_UNIT_READY:
2788 case VERIFY:
2789 case START_STOP:
2790 TRACE2(("Test/Verify/Start hdrive %d\n",t));
2791 break;
2792
2793 case INQUIRY:
2794 TRACE2(("Inquiry hdrive %d devtype %d\n",
2795 t,ha->hdr[t].devtype));
2796 inq.type_qual = (ha->hdr[t].devtype&4) ? TYPE_ROM:TYPE_DISK;
2797
2798
2799 inq.modif_rmb = 0x00;
2800 if ((ha->hdr[t].devtype & 1) ||
2801 (ha->hdr[t].cluster_type & CLUSTER_DRIVE))
2802 inq.modif_rmb = 0x80;
2803 inq.version = 2;
2804 inq.resp_aenc = 2;
2805 inq.add_length= 32;
2806 strcpy(inq.vendor,ha->oem_name);
2807 sprintf(inq.product,"Host Drive #%02d",t);
2808 strcpy(inq.revision," ");
2809 gdth_copy_internal_data(hanum,scp,(char*)&inq,sizeof(gdth_inq_data));
2810 break;
2811
2812 case REQUEST_SENSE:
2813 TRACE2(("Request sense hdrive %d\n",t));
2814 sd.errorcode = 0x70;
2815 sd.segno = 0x00;
2816 sd.key = NO_SENSE;
2817 sd.info = 0;
2818 sd.add_length= 0;
2819 gdth_copy_internal_data(hanum,scp,(char*)&sd,sizeof(gdth_sense_data));
2820 break;
2821
2822 case MODE_SENSE:
2823 TRACE2(("Mode sense hdrive %d\n",t));
2824 memset((char*)&mpd,0,sizeof(gdth_modep_data));
2825 mpd.hd.data_length = sizeof(gdth_modep_data);
2826 mpd.hd.dev_par = (ha->hdr[t].devtype&2) ? 0x80:0;
2827 mpd.hd.bd_length = sizeof(mpd.bd);
2828 mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16;
2829 mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8;
2830 mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff);
2831 gdth_copy_internal_data(hanum,scp,(char*)&mpd,sizeof(gdth_modep_data));
2832 break;
2833
2834 case READ_CAPACITY:
2835 TRACE2(("Read capacity hdrive %d\n",t));
2836 if (ha->hdr[t].size > (ulong64)0xffffffff)
2837 rdc.last_block_no = 0xffffffff;
2838 else
2839 rdc.last_block_no = cpu_to_be32(ha->hdr[t].size-1);
2840 rdc.block_length = cpu_to_be32(SECTOR_SIZE);
2841 gdth_copy_internal_data(hanum,scp,(char*)&rdc,sizeof(gdth_rdcap_data));
2842 break;
2843
2844#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
2845 case SERVICE_ACTION_IN:
2846 if ((scp->cmnd[1] & 0x1f) == SAI_READ_CAPACITY_16 &&
2847 (ha->cache_feat & GDT_64BIT)) {
2848 gdth_rdcap16_data rdc16;
2849
2850 TRACE2(("Read capacity (16) hdrive %d\n",t));
2851 rdc16.last_block_no = cpu_to_be64(ha->hdr[t].size-1);
2852 rdc16.block_length = cpu_to_be32(SECTOR_SIZE);
2853 gdth_copy_internal_data(hanum,scp,(char*)&rdc16,sizeof(gdth_rdcap16_data));
2854 } else {
2855 scp->result = DID_ABORT << 16;
2856 }
2857 break;
2858#endif
2859
2860 default:
2861 TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0]));
2862 break;
2863 }
2864
2865 if (!scp->SCp.have_data_in)
2866 scp->SCp.have_data_in++;
2867 else
2868 return 1;
2869
2870 return 0;
2871}
2872
2873static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
2874{
2875 register gdth_ha_str *ha;
2876 register gdth_cmd_str *cmdp;
2877 struct scatterlist *sl;
2878 ulong32 cnt, blockcnt;
2879 ulong64 no, blockno;
2880 dma_addr_t phys_addr;
2881 int i, cmd_index, read_write, sgcnt, mode64;
2882#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
2883 struct page *page;
2884 ulong offset;
2885#endif
2886
2887 ha = HADATA(gdth_ctr_tab[hanum]);
2888 cmdp = ha->pccb;
2889 TRACE(("gdth_fill_cache_cmd() cmd 0x%x cmdsize %d hdrive %d\n",
2890 scp->cmnd[0],scp->cmd_len,hdrive));
2891
2892 if (ha->type==GDT_EISA && ha->cmd_cnt>0)
2893 return 0;
2894
2895 mode64 = (ha->cache_feat & GDT_64BIT) ? TRUE : FALSE;
2896
2897
2898
2899
2900 cmdp->Service = CACHESERVICE;
2901 cmdp->RequestBuffer = scp;
2902
2903 if (!(cmd_index=gdth_get_cmd_index(hanum))) {
2904 TRACE(("GDT: No free command index found\n"));
2905 return 0;
2906 }
2907
2908 if (ha->cmd_cnt == 0)
2909 gdth_set_sema0(hanum);
2910
2911
2912 read_write = 0;
2913 if (scp->SCp.sent_command != -1)
2914 cmdp->OpCode = scp->SCp.sent_command;
2915 else if (scp->cmnd[0] == RESERVE)
2916 cmdp->OpCode = GDT_RESERVE_DRV;
2917 else if (scp->cmnd[0] == RELEASE)
2918 cmdp->OpCode = GDT_RELEASE_DRV;
2919 else if (scp->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
2920 if (scp->cmnd[4] & 1)
2921 cmdp->OpCode = GDT_MOUNT;
2922 else if (scp->cmnd[3] & 1)
2923 cmdp->OpCode = GDT_UNMOUNT;
2924 else
2925 cmdp->OpCode = GDT_FLUSH;
2926 } else if (scp->cmnd[0] == WRITE_6 || scp->cmnd[0] == WRITE_10 ||
2927 scp->cmnd[0] == WRITE_12
2928#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
2929 || scp->cmnd[0] == WRITE_16
2930#endif
2931 ) {
2932 read_write = 1;
2933 if (gdth_write_through || ((ha->hdr[hdrive].rw_attribs & 1) &&
2934 (ha->cache_feat & GDT_WR_THROUGH)))
2935 cmdp->OpCode = GDT_WRITE_THR;
2936 else
2937 cmdp->OpCode = GDT_WRITE;
2938 } else {
2939 read_write = 2;
2940 cmdp->OpCode = GDT_READ;
2941 }
2942
2943 cmdp->BoardNode = LOCALBOARD;
2944 if (mode64) {
2945 cmdp->u.cache64.DeviceNo = hdrive;
2946 cmdp->u.cache64.BlockNo = 1;
2947 cmdp->u.cache64.sg_canz = 0;
2948 } else {
2949 cmdp->u.cache.DeviceNo = hdrive;
2950 cmdp->u.cache.BlockNo = 1;
2951 cmdp->u.cache.sg_canz = 0;
2952 }
2953
2954 if (read_write) {
2955 if (scp->cmd_len == 16) {
2956 memcpy(&no, &scp->cmnd[2], sizeof(ulong64));
2957 blockno = be64_to_cpu(no);
2958 memcpy(&cnt, &scp->cmnd[10], sizeof(ulong32));
2959 blockcnt = be32_to_cpu(cnt);
2960 } else if (scp->cmd_len == 10) {
2961 memcpy(&no, &scp->cmnd[2], sizeof(ulong32));
2962 blockno = be32_to_cpu(no);
2963 memcpy(&cnt, &scp->cmnd[7], sizeof(ushort));
2964 blockcnt = be16_to_cpu(cnt);
2965 } else {
2966 memcpy(&no, &scp->cmnd[0], sizeof(ulong32));
2967 blockno = be32_to_cpu(no) & 0x001fffffUL;
2968 blockcnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4];
2969 }
2970 if (mode64) {
2971 cmdp->u.cache64.BlockNo = blockno;
2972 cmdp->u.cache64.BlockCnt = blockcnt;
2973 } else {
2974 cmdp->u.cache.BlockNo = (ulong32)blockno;
2975 cmdp->u.cache.BlockCnt = blockcnt;
2976 }
2977
2978 if (scp->use_sg) {
2979 sl = (struct scatterlist *)scp->request_buffer;
2980 sgcnt = scp->use_sg;
2981#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
2982 scp->SCp.Status = GDTH_MAP_SG;
2983 scp->SCp.Message = (read_write == 1 ?
2984 PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
2985 sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message);
2986 if (mode64) {
2987 cmdp->u.cache64.DestAddr= (ulong64)-1;
2988 cmdp->u.cache64.sg_canz = sgcnt;
2989 for (i=0; i<sgcnt; ++i,++sl) {
2990 cmdp->u.cache64.sg_lst[i].sg_ptr = sg_dma_address(sl);
2991#ifdef GDTH_DMA_STATISTICS
2992 if (cmdp->u.cache64.sg_lst[i].sg_ptr > (ulong64)0xffffffff)
2993 ha->dma64_cnt++;
2994 else
2995 ha->dma32_cnt++;
2996#endif
2997 cmdp->u.cache64.sg_lst[i].sg_len = sg_dma_len(sl);
2998 }
2999 } else {
3000 cmdp->u.cache.DestAddr= 0xffffffff;
3001 cmdp->u.cache.sg_canz = sgcnt;
3002 for (i=0; i<sgcnt; ++i,++sl) {
3003 cmdp->u.cache.sg_lst[i].sg_ptr = sg_dma_address(sl);
3004#ifdef GDTH_DMA_STATISTICS
3005 ha->dma32_cnt++;
3006#endif
3007 cmdp->u.cache.sg_lst[i].sg_len = sg_dma_len(sl);
3008 }
3009 }
3010#else
3011 if (mode64) {
3012 cmdp->u.cache64.DestAddr= (ulong64)-1;
3013 cmdp->u.cache64.sg_canz = sgcnt;
3014 for (i=0; i<sgcnt; ++i,++sl) {
3015 cmdp->u.cache64.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
3016 cmdp->u.cache64.sg_lst[i].sg_len = (ulong32)sl->length;
3017 }
3018 } else {
3019 cmdp->u.cache.DestAddr= 0xffffffff;
3020 cmdp->u.cache.sg_canz = sgcnt;
3021 for (i=0; i<sgcnt; ++i,++sl) {
3022 cmdp->u.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
3023 cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length;
3024 }
3025 }
3026#endif
3027
3028#ifdef GDTH_STATISTICS
3029 if (max_sg < (ulong32)sgcnt) {
3030 max_sg = (ulong32)sgcnt;
3031 TRACE3(("GDT: max_sg = %d\n",max_sg));
3032 }
3033#endif
3034
3035 } else {
3036#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
3037 scp->SCp.Status = GDTH_MAP_SINGLE;
3038 scp->SCp.Message = (read_write == 1 ?
3039 PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
3040 page = virt_to_page(scp->request_buffer);
3041 offset = (ulong)scp->request_buffer & ~PAGE_MASK;
3042 phys_addr = pci_map_page(ha->pdev,page,offset,
3043 scp->request_bufflen,scp->SCp.Message);
3044 scp->SCp.dma_handle = phys_addr;
3045#else
3046 phys_addr = virt_to_bus(scp->request_buffer);
3047#endif
3048 if (mode64) {
3049 if (ha->cache_feat & SCATTER_GATHER) {
3050 cmdp->u.cache64.DestAddr = (ulong64)-1;
3051 cmdp->u.cache64.sg_canz = 1;
3052 cmdp->u.cache64.sg_lst[0].sg_ptr = phys_addr;
3053 cmdp->u.cache64.sg_lst[0].sg_len = scp->request_bufflen;
3054 cmdp->u.cache64.sg_lst[1].sg_len = 0;
3055 } else {
3056 cmdp->u.cache64.DestAddr = phys_addr;
3057 cmdp->u.cache64.sg_canz= 0;
3058 }
3059 } else {
3060 if (ha->cache_feat & SCATTER_GATHER) {
3061 cmdp->u.cache.DestAddr = 0xffffffff;
3062 cmdp->u.cache.sg_canz = 1;
3063 cmdp->u.cache.sg_lst[0].sg_ptr = phys_addr;
3064 cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen;
3065 cmdp->u.cache.sg_lst[1].sg_len = 0;
3066 } else {
3067 cmdp->u.cache.DestAddr = phys_addr;
3068 cmdp->u.cache.sg_canz= 0;
3069 }
3070 }
3071 }
3072 }
3073
3074 if (mode64) {
3075 TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
3076 cmdp->u.cache64.DestAddr,cmdp->u.cache64.sg_canz,
3077 cmdp->u.cache64.sg_lst[0].sg_ptr,
3078 cmdp->u.cache64.sg_lst[0].sg_len));
3079 TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n",
3080 cmdp->OpCode,cmdp->u.cache64.BlockNo,cmdp->u.cache64.BlockCnt));
3081 ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache64.sg_lst) +
3082 (ushort)cmdp->u.cache64.sg_canz * sizeof(gdth_sg64_str);
3083 } else {
3084 TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
3085 cmdp->u.cache.DestAddr,cmdp->u.cache.sg_canz,
3086 cmdp->u.cache.sg_lst[0].sg_ptr,
3087 cmdp->u.cache.sg_lst[0].sg_len));
3088 TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n",
3089 cmdp->OpCode,cmdp->u.cache.BlockNo,cmdp->u.cache.BlockCnt));
3090 ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) +
3091 (ushort)cmdp->u.cache.sg_canz * sizeof(gdth_sg_str);
3092 }
3093 if (ha->cmd_len & 3)
3094 ha->cmd_len += (4 - (ha->cmd_len & 3));
3095
3096 if (ha->cmd_cnt > 0) {
3097 if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
3098 ha->ic_all_size) {
3099 TRACE2(("gdth_fill_cache() DPMEM overflow\n"));
3100 ha->cmd_tab[cmd_index-2].cmnd = UNUSED_CMND;
3101 return 0;
3102 }
3103 }
3104
3105
3106 gdth_copy_command(hanum);
3107 return cmd_index;
3108}
3109
3110static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
3111{
3112 register gdth_ha_str *ha;
3113 register gdth_cmd_str *cmdp;
3114 struct scatterlist *sl;
3115 ushort i;
3116 dma_addr_t phys_addr, sense_paddr;
3117 int cmd_index, sgcnt, mode64;
3118 unchar t,l;
3119#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
3120 struct page *page;
3121 ulong offset;
3122#endif
3123
3124 ha = HADATA(gdth_ctr_tab[hanum]);
3125#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
3126 t = scp->device->id;
3127 l = scp->device->lun;
3128#else
3129 t = scp->target;
3130 l = scp->lun;
3131#endif
3132 cmdp = ha->pccb;
3133 TRACE(("gdth_fill_raw_cmd() cmd 0x%x bus %d ID %d LUN %d\n",
3134 scp->cmnd[0],b,t,l));
3135
3136 if (ha->type==GDT_EISA && ha->cmd_cnt>0)
3137 return 0;
3138
3139 mode64 = (ha->raw_feat & GDT_64BIT) ? TRUE : FALSE;
3140
3141 cmdp->Service = SCSIRAWSERVICE;
3142 cmdp->RequestBuffer = scp;
3143
3144 if (!(cmd_index=gdth_get_cmd_index(hanum))) {
3145 TRACE(("GDT: No free command index found\n"));
3146 return 0;
3147 }
3148
3149 if (ha->cmd_cnt == 0)
3150 gdth_set_sema0(hanum);
3151
3152
3153 if (scp->SCp.sent_command != -1) {
3154 cmdp->OpCode = scp->SCp.sent_command;
3155 cmdp->BoardNode = LOCALBOARD;
3156 if (mode64) {
3157 cmdp->u.raw64.direction = (scp->SCp.phase >> 8);
3158 TRACE2(("special raw cmd 0x%x param 0x%x\n",
3159 cmdp->OpCode, cmdp->u.raw64.direction));
3160
3161 ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst);
3162 } else {
3163 cmdp->u.raw.direction = (scp->SCp.phase >> 8);
3164 TRACE2(("special raw cmd 0x%x param 0x%x\n",
3165 cmdp->OpCode, cmdp->u.raw.direction));
3166
3167 ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst);
3168 }
3169
3170 } else {
3171#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
3172 page = virt_to_page(scp->sense_buffer);
3173 offset = (ulong)scp->sense_buffer & ~PAGE_MASK;
3174 sense_paddr = pci_map_page(ha->pdev,page,offset,
3175 16,PCI_DMA_FROMDEVICE);
3176 scp->SCp.buffer = (struct scatterlist *)((ulong32)sense_paddr);
3177
3178 scp->host_scribble = (char *)(ulong32)((ulong64)sense_paddr >> 32);
3179#else
3180 sense_paddr = virt_to_bus(scp->sense_buffer);
3181#endif
3182 cmdp->OpCode = GDT_WRITE;
3183 cmdp->BoardNode = LOCALBOARD;
3184 if (mode64) {
3185 cmdp->u.raw64.reserved = 0;
3186 cmdp->u.raw64.mdisc_time = 0;
3187 cmdp->u.raw64.mcon_time = 0;
3188 cmdp->u.raw64.clen = scp->cmd_len;
3189 cmdp->u.raw64.target = t;
3190 cmdp->u.raw64.lun = l;
3191 cmdp->u.raw64.bus = b;
3192 cmdp->u.raw64.priority = 0;
3193 cmdp->u.raw64.sdlen = scp->request_bufflen;
3194 cmdp->u.raw64.sense_len = 16;
3195 cmdp->u.raw64.sense_data = sense_paddr;
3196 cmdp->u.raw64.direction =
3197 gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN;
3198 memcpy(cmdp->u.raw64.cmd,scp->cmnd,16);
3199 } else {
3200 cmdp->u.raw.reserved = 0;
3201 cmdp->u.raw.mdisc_time = 0;
3202 cmdp->u.raw.mcon_time = 0;
3203 cmdp->u.raw.clen = scp->cmd_len;
3204 cmdp->u.raw.target = t;
3205 cmdp->u.raw.lun = l;
3206 cmdp->u.raw.bus = b;
3207 cmdp->u.raw.priority = 0;
3208 cmdp->u.raw.link_p = 0;
3209 cmdp->u.raw.sdlen = scp->request_bufflen;
3210 cmdp->u.raw.sense_len = 16;
3211 cmdp->u.raw.sense_data = sense_paddr;
3212 cmdp->u.raw.direction =
3213 gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN;
3214 memcpy(cmdp->u.raw.cmd,scp->cmnd,12);
3215 }
3216
3217 if (scp->use_sg) {
3218 sl = (struct scatterlist *)scp->request_buffer;
3219 sgcnt = scp->use_sg;
3220#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
3221 scp->SCp.Status = GDTH_MAP_SG;
3222 scp->SCp.Message = PCI_DMA_BIDIRECTIONAL;
3223 sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message);
3224 if (mode64) {
3225 cmdp->u.raw64.sdata = (ulong64)-1;
3226 cmdp->u.raw64.sg_ranz = sgcnt;
3227 for (i=0; i<sgcnt; ++i,++sl) {
3228 cmdp->u.raw64.sg_lst[i].sg_ptr = sg_dma_address(sl);
3229#ifdef GDTH_DMA_STATISTICS
3230 if (cmdp->u.raw64.sg_lst[i].sg_ptr > (ulong64)0xffffffff)
3231 ha->dma64_cnt++;
3232 else
3233 ha->dma32_cnt++;
3234#endif
3235 cmdp->u.raw64.sg_lst[i].sg_len = sg_dma_len(sl);
3236 }
3237 } else {
3238 cmdp->u.raw.sdata = 0xffffffff;
3239 cmdp->u.raw.sg_ranz = sgcnt;
3240 for (i=0; i<sgcnt; ++i,++sl) {
3241 cmdp->u.raw.sg_lst[i].sg_ptr = sg_dma_address(sl);
3242#ifdef GDTH_DMA_STATISTICS
3243 ha->dma32_cnt++;
3244#endif
3245 cmdp->u.raw.sg_lst[i].sg_len = sg_dma_len(sl);
3246 }
3247 }
3248#else
3249 if (mode64) {
3250 cmdp->u.raw64.sdata = (ulong64)-1;
3251 cmdp->u.raw64.sg_ranz = sgcnt;
3252 for (i=0; i<sgcnt; ++i,++sl) {
3253 cmdp->u.raw64.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
3254 cmdp->u.raw64.sg_lst[i].sg_len = (ulong32)sl->length;
3255 }
3256 } else {
3257 cmdp->u.raw.sdata = 0xffffffff;
3258 cmdp->u.raw.sg_ranz = sgcnt;
3259 for (i=0; i<sgcnt; ++i,++sl) {
3260 cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
3261 cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length;
3262 }
3263 }
3264#endif
3265
3266#ifdef GDTH_STATISTICS
3267 if (max_sg < sgcnt) {
3268 max_sg = sgcnt;
3269 TRACE3(("GDT: max_sg = %d\n",sgcnt));
3270 }
3271#endif
3272
3273 } else {
3274#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
3275 scp->SCp.Status = GDTH_MAP_SINGLE;
3276 scp->SCp.Message = PCI_DMA_BIDIRECTIONAL;
3277 page = virt_to_page(scp->request_buffer);
3278 offset = (ulong)scp->request_buffer & ~PAGE_MASK;
3279 phys_addr = pci_map_page(ha->pdev,page,offset,
3280 scp->request_bufflen,scp->SCp.Message);
3281 scp->SCp.dma_handle = phys_addr;
3282#else
3283 phys_addr = virt_to_bus(scp->request_buffer);
3284#endif
3285 if (mode64) {
3286 if (ha->raw_feat & SCATTER_GATHER) {
3287 cmdp->u.raw64.sdata = (ulong64)-1;
3288 cmdp->u.raw64.sg_ranz= 1;
3289 cmdp->u.raw64.sg_lst[0].sg_ptr = phys_addr;
3290 cmdp->u.raw64.sg_lst[0].sg_len = scp->request_bufflen;
3291 cmdp->u.raw64.sg_lst[1].sg_len = 0;
3292 } else {
3293 cmdp->u.raw64.sdata = phys_addr;
3294 cmdp->u.raw64.sg_ranz= 0;
3295 }
3296 } else {
3297 if (ha->raw_feat & SCATTER_GATHER) {
3298 cmdp->u.raw.sdata = 0xffffffff;
3299 cmdp->u.raw.sg_ranz= 1;
3300 cmdp->u.raw.sg_lst[0].sg_ptr = phys_addr;
3301 cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen;
3302 cmdp->u.raw.sg_lst[1].sg_len = 0;
3303 } else {
3304 cmdp->u.raw.sdata = phys_addr;
3305 cmdp->u.raw.sg_ranz= 0;
3306 }
3307 }
3308 }
3309 if (mode64) {
3310 TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
3311 cmdp->u.raw64.sdata,cmdp->u.raw64.sg_ranz,
3312 cmdp->u.raw64.sg_lst[0].sg_ptr,
3313 cmdp->u.raw64.sg_lst[0].sg_len));
3314
3315 ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst) +
3316 (ushort)cmdp->u.raw64.sg_ranz * sizeof(gdth_sg64_str);
3317 } else {
3318 TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
3319 cmdp->u.raw.sdata,cmdp->u.raw.sg_ranz,
3320 cmdp->u.raw.sg_lst[0].sg_ptr,
3321 cmdp->u.raw.sg_lst[0].sg_len));
3322
3323 ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) +
3324 (ushort)cmdp->u.raw.sg_ranz * sizeof(gdth_sg_str);
3325 }
3326 }
3327
3328 if (ha->cmd_len & 3)
3329 ha->cmd_len += (4 - (ha->cmd_len & 3));
3330
3331 if (ha->cmd_cnt > 0) {
3332 if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
3333 ha->ic_all_size) {
3334 TRACE2(("gdth_fill_raw() DPMEM overflow\n"));
3335 ha->cmd_tab[cmd_index-2].cmnd = UNUSED_CMND;
3336 return 0;
3337 }
3338 }
3339
3340
3341 gdth_copy_command(hanum);
3342 return cmd_index;
3343}
3344
3345static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp)
3346{
3347 register gdth_ha_str *ha;
3348 register gdth_cmd_str *cmdp;
3349 int cmd_index;
3350
3351 ha = HADATA(gdth_ctr_tab[hanum]);
3352 cmdp= ha->pccb;
3353 TRACE2(("gdth_special_cmd(): "));
3354
3355 if (ha->type==GDT_EISA && ha->cmd_cnt>0)
3356 return 0;
3357
3358 memcpy( cmdp, scp->request_buffer, sizeof(gdth_cmd_str));
3359 cmdp->RequestBuffer = scp;
3360
3361
3362 if (!(cmd_index=gdth_get_cmd_index(hanum))) {
3363 TRACE(("GDT: No free command index found\n"));
3364 return 0;
3365 }
3366
3367
3368 if (ha->cmd_cnt == 0)
3369 gdth_set_sema0(hanum);
3370
3371
3372 if (cmdp->OpCode == GDT_IOCTL) {
3373 TRACE2(("IOCTL\n"));
3374 ha->cmd_len =
3375 GDTOFFSOF(gdth_cmd_str,u.ioctl.p_param) + sizeof(ulong64);
3376 } else if (cmdp->Service == CACHESERVICE) {
3377 TRACE2(("cache command %d\n",cmdp->OpCode));
3378 if (ha->cache_feat & GDT_64BIT)
3379 ha->cmd_len =
3380 GDTOFFSOF(gdth_cmd_str,u.cache64.sg_lst) + sizeof(gdth_sg64_str);
3381 else
3382 ha->cmd_len =
3383 GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + sizeof(gdth_sg_str);
3384 } else if (cmdp->Service == SCSIRAWSERVICE) {
3385 TRACE2(("raw command %d\n",cmdp->OpCode));
3386 if (ha->raw_feat & GDT_64BIT)
3387 ha->cmd_len =
3388 GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst) + sizeof(gdth_sg64_str);
3389 else
3390 ha->cmd_len =
3391 GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + sizeof(gdth_sg_str);
3392 }
3393
3394 if (ha->cmd_len & 3)
3395 ha->cmd_len += (4 - (ha->cmd_len & 3));
3396
3397 if (ha->cmd_cnt > 0) {
3398 if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
3399 ha->ic_all_size) {
3400 TRACE2(("gdth_special_cmd() DPMEM overflow\n"));
3401 ha->cmd_tab[cmd_index-2].cmnd = UNUSED_CMND;
3402 return 0;
3403 }
3404 }
3405
3406
3407 gdth_copy_command(hanum);
3408 return cmd_index;
3409}
3410
3411
3412
3413static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source,
3414 ushort idx, gdth_evt_data *evt)
3415{
3416 gdth_evt_str *e;
3417 struct timeval tv;
3418
3419
3420 TRACE2(("gdth_store_event() source %d idx %d\n", source, idx));
3421 if (source == 0)
3422 return 0;
3423
3424 if (ebuffer[elastidx].event_source == source &&
3425 ebuffer[elastidx].event_idx == idx &&
3426 ((evt->size != 0 && ebuffer[elastidx].event_data.size != 0 &&
3427 !memcmp((char *)&ebuffer[elastidx].event_data.eu,
3428 (char *)&evt->eu, evt->size)) ||
3429 (evt->size == 0 && ebuffer[elastidx].event_data.size == 0 &&
3430 !strcmp((char *)&ebuffer[elastidx].event_data.event_string,
3431 (char *)&evt->event_string)))) {
3432 e = &ebuffer[elastidx];
3433 do_gettimeofday(&tv);
3434 e->last_stamp = tv.tv_sec;
3435 ++e->same_count;
3436 } else {
3437 if (ebuffer[elastidx].event_source != 0) {
3438 ++elastidx;
3439 if (elastidx == MAX_EVENTS)
3440 elastidx = 0;
3441 if (elastidx == eoldidx) {
3442 ++eoldidx;
3443 if (eoldidx == MAX_EVENTS)
3444 eoldidx = 0;
3445 }
3446 }
3447 e = &ebuffer[elastidx];
3448 e->event_source = source;
3449 e->event_idx = idx;
3450 do_gettimeofday(&tv);
3451 e->first_stamp = e->last_stamp = tv.tv_sec;
3452 e->same_count = 1;
3453 e->event_data = *evt;
3454 e->application = 0;
3455 }
3456 return e;
3457}
3458
3459static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr)
3460{
3461 gdth_evt_str *e;
3462 int eindex;
3463 ulong flags;
3464
3465 TRACE2(("gdth_read_event() handle %d\n", handle));
3466 GDTH_LOCK_HA(ha, flags);
3467 if (handle == -1)
3468 eindex = eoldidx;
3469 else
3470 eindex = handle;
3471 estr->event_source = 0;
3472
3473 if (eindex >= MAX_EVENTS) {
3474 GDTH_UNLOCK_HA(ha, flags);
3475 return eindex;
3476 }
3477 e = &ebuffer[eindex];
3478 if (e->event_source != 0) {
3479 if (eindex != elastidx) {
3480 if (++eindex == MAX_EVENTS)
3481 eindex = 0;
3482 } else {
3483 eindex = -1;
3484 }
3485 memcpy(estr, e, sizeof(gdth_evt_str));
3486 }
3487 GDTH_UNLOCK_HA(ha, flags);
3488 return eindex;
3489}
3490
3491static void gdth_readapp_event(gdth_ha_str *ha,
3492 unchar application, gdth_evt_str *estr)
3493{
3494 gdth_evt_str *e;
3495 int eindex;
3496 ulong flags;
3497 unchar found = FALSE;
3498
3499 TRACE2(("gdth_readapp_event() app. %d\n", application));
3500 GDTH_LOCK_HA(ha, flags);
3501 eindex = eoldidx;
3502 for (;;) {
3503 e = &ebuffer[eindex];
3504 if (e->event_source == 0)
3505 break;
3506 if ((e->application & application) == 0) {
3507 e->application |= application;
3508 found = TRUE;
3509 break;
3510 }
3511 if (eindex == elastidx)
3512 break;
3513 if (++eindex == MAX_EVENTS)
3514 eindex = 0;
3515 }
3516 if (found)
3517 memcpy(estr, e, sizeof(gdth_evt_str));
3518 else
3519 estr->event_source = 0;
3520 GDTH_UNLOCK_HA(ha, flags);
3521}
3522
3523static void gdth_clear_events()
3524{
3525 TRACE(("gdth_clear_events()"));
3526
3527 eoldidx = elastidx = 0;
3528 ebuffer[0].event_source = 0;
3529}
3530
3531
3532
3533
3534#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
3535static irqreturn_t gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
3536#else
3537static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
3538#endif
3539{
3540 register gdth_ha_str *ha;
3541 gdt6m_dpram_str *dp6m_ptr = NULL;
3542 gdt6_dpram_str *dp6_ptr;
3543 gdt2_dpram_str *dp2_ptr;
3544 Scsi_Cmnd *scp;
3545 int hanum, rval, i;
3546 unchar IStatus;
3547 ushort Service;
3548 ulong flags = 0;
3549#ifdef INT_COAL
3550 int coalesced = FALSE;
3551 int next = FALSE;
3552 gdth_coal_status *pcs = NULL;
3553 int act_int_coal = 0;
3554#endif
3555
3556 TRACE(("gdth_interrupt() IRQ %d\n",irq));
3557
3558
3559 if (gdth_polling) {
3560 if (!gdth_from_wait) {
3561#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
3562 return IRQ_HANDLED;
3563#else
3564 return;
3565#endif
3566 }
3567 }
3568
3569 if (!gdth_polling)
3570 GDTH_LOCK_HA((gdth_ha_str *)dev_id,flags);
3571 wait_index = 0;
3572
3573
3574 if ((hanum = gdth_get_status(&IStatus,irq)) == -1) {
3575
3576 if (!gdth_polling)
3577 GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
3578#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
3579 return IRQ_HANDLED;
3580#else
3581 return;
3582#endif
3583 }
3584 ha = HADATA(gdth_ctr_tab[hanum]);
3585
3586#ifdef GDTH_STATISTICS
3587 ++act_ints;
3588#endif
3589
3590#ifdef INT_COAL
3591
3592 if (IStatus == COALINDEX) {
3593
3594
3595 pcs = ha->coal_stat;
3596 coalesced = TRUE;
3597 next = TRUE;
3598 }
3599
3600 do {
3601 if (coalesced) {
3602
3603
3604 IStatus = (unchar)(pcs->status & 0xff);
3605 }
3606#endif
3607
3608 if (ha->type == GDT_EISA) {
3609 if (IStatus & 0x80) {
3610 IStatus &= ~0x80;
3611 ha->status = inw(ha->bmic + MAILBOXREG+8);
3612 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
3613 } else
3614 ha->status = S_OK;
3615 ha->info = inl(ha->bmic + MAILBOXREG+12);
3616 ha->service = inw(ha->bmic + MAILBOXREG+10);
3617 ha->info2 = inl(ha->bmic + MAILBOXREG+4);
3618
3619 outb(0xff, ha->bmic + EDOORREG);
3620 outb(0x00, ha->bmic + SEMA1REG);
3621 } else if (ha->type == GDT_ISA) {
3622 dp2_ptr = (gdt2_dpram_str *)ha->brd;
3623 if (IStatus & 0x80) {
3624 IStatus &= ~0x80;
3625 ha->status = gdth_readw(&dp2_ptr->u.ic.Status);
3626 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
3627 } else
3628 ha->status = S_OK;
3629 ha->info = gdth_readl(&dp2_ptr->u.ic.Info[0]);
3630 ha->service = gdth_readw(&dp2_ptr->u.ic.Service);
3631 ha->info2 = gdth_readl(&dp2_ptr->u.ic.Info[1]);
3632
3633 gdth_writeb(0xff, &dp2_ptr->io.irqdel);
3634 gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);
3635 gdth_writeb(0, &dp2_ptr->io.Sema1);
3636 } else if (ha->type == GDT_PCI) {
3637 dp6_ptr = (gdt6_dpram_str *)ha->brd;
3638 if (IStatus & 0x80) {
3639 IStatus &= ~0x80;
3640 ha->status = gdth_readw(&dp6_ptr->u.ic.Status);
3641 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
3642 } else
3643 ha->status = S_OK;
3644 ha->info = gdth_readl(&dp6_ptr->u.ic.Info[0]);
3645 ha->service = gdth_readw(&dp6_ptr->u.ic.Service);
3646 ha->info2 = gdth_readl(&dp6_ptr->u.ic.Info[1]);
3647
3648 gdth_writeb(0xff, &dp6_ptr->io.irqdel);
3649 gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index);
3650 gdth_writeb(0, &dp6_ptr->io.Sema1);
3651 } else if (ha->type == GDT_PCINEW) {
3652 if (IStatus & 0x80) {
3653 IStatus &= ~0x80;
3654 ha->status = inw(PTR2USHORT(&ha->plx->status));
3655 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
3656 } else
3657 ha->status = S_OK;
3658 ha->info = inl(PTR2USHORT(&ha->plx->info[0]));
3659 ha->service = inw(PTR2USHORT(&ha->plx->service));
3660 ha->info2 = inl(PTR2USHORT(&ha->plx->info[1]));
3661
3662 outb(0xff, PTR2USHORT(&ha->plx->edoor_reg));
3663 outb(0x00, PTR2USHORT(&ha->plx->sema1_reg));
3664 } else if (ha->type == GDT_PCIMPR) {
3665 dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
3666 if (IStatus & 0x80) {
3667 IStatus &= ~0x80;
3668#ifdef INT_COAL
3669 if (coalesced)
3670 ha->status = pcs->ext_status && 0xffff;
3671 else
3672#endif
3673 ha->status = gdth_readw(&dp6m_ptr->i960r.status);
3674 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
3675 } else
3676 ha->status = S_OK;
3677#ifdef INT_COAL
3678
3679 if (coalesced) {
3680 ha->info = pcs->info0;
3681 ha->info2 = pcs->info1;
3682 ha->service = (pcs->ext_status >> 16) && 0xffff;
3683 } else
3684#endif
3685 {
3686 ha->info = gdth_readl(&dp6m_ptr->i960r.info[0]);
3687 ha->service = gdth_readw(&dp6m_ptr->i960r.service);
3688 ha->info2 = gdth_readl(&dp6m_ptr->i960r.info[1]);
3689 }
3690
3691 if (IStatus == ASYNCINDEX) {
3692 if (ha->service != SCREENSERVICE &&
3693 (ha->fw_vers & 0xff) >= 0x1a) {
3694 ha->dvr.severity = gdth_readb
3695 (&((gdt6m_dpram_str *)ha->brd)->i960r.severity);
3696 for (i = 0; i < 256; ++i) {
3697 ha->dvr.event_string[i] = gdth_readb
3698 (&((gdt6m_dpram_str *)ha->brd)->i960r.evt_str[i]);
3699 if (ha->dvr.event_string[i] == 0)
3700 break;
3701 }
3702 }
3703 }
3704#ifdef INT_COAL
3705
3706
3707 if (!coalesced)
3708#endif
3709 {
3710 gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
3711 gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg);
3712 }
3713 } else {
3714 TRACE2(("gdth_interrupt() unknown controller type\n"));
3715 if (!gdth_polling)
3716 GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
3717#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
3718 return IRQ_HANDLED;
3719#else
3720 return;
3721#endif
3722 }
3723
3724 TRACE(("gdth_interrupt() index %d stat %d info %d\n",
3725 IStatus,ha->status,ha->info));
3726
3727 if (gdth_from_wait) {
3728 wait_hanum = hanum;
3729 wait_index = (int)IStatus;
3730 }
3731
3732 if (IStatus == ASYNCINDEX) {
3733 TRACE2(("gdth_interrupt() async. event\n"));
3734 gdth_async_event(hanum);
3735 if (!gdth_polling)
3736 GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
3737 gdth_next(hanum);
3738#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
3739 return IRQ_HANDLED;
3740#else
3741 return;
3742#endif
3743 }
3744
3745 if (IStatus == SPEZINDEX) {
3746 TRACE2(("Service unknown or not initialized !\n"));
3747 ha->dvr.size = sizeof(ha->dvr.eu.driver);
3748 ha->dvr.eu.driver.ionode = hanum;
3749 gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr);
3750 if (!gdth_polling)
3751 GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
3752#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
3753 return IRQ_HANDLED;
3754#else
3755 return;
3756#endif
3757 }
3758 scp = ha->cmd_tab[IStatus-2].cmnd;
3759 Service = ha->cmd_tab[IStatus-2].service;
3760 ha->cmd_tab[IStatus-2].cmnd = UNUSED_CMND;
3761 if (scp == UNUSED_CMND) {
3762 TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus));
3763 ha->dvr.size = sizeof(ha->dvr.eu.driver);
3764 ha->dvr.eu.driver.ionode = hanum;
3765 ha->dvr.eu.driver.index = IStatus;
3766 gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr);
3767 if (!gdth_polling)
3768 GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
3769#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
3770 return IRQ_HANDLED;
3771#else
3772 return;
3773#endif
3774 }
3775 if (scp == INTERNAL_CMND) {
3776 TRACE(("gdth_interrupt() answer to internal command\n"));
3777 if (!gdth_polling)
3778 GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
3779#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
3780 return IRQ_HANDLED;
3781#else
3782 return;
3783#endif
3784 }
3785
3786 TRACE(("gdth_interrupt() sync. status\n"));
3787 rval = gdth_sync_event(hanum,Service,IStatus,scp);
3788 if (!gdth_polling)
3789 GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
3790 if (rval == 2) {
3791 gdth_putq(hanum,scp,scp->SCp.this_residual);
3792 } else if (rval == 1) {
3793#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
3794 GDTH_LOCK_SCSI_DONE(scp->device->host, flags);
3795 scp->scsi_done(scp);
3796 GDTH_UNLOCK_SCSI_DONE(scp->device->host, flags);
3797#else
3798 GDTH_LOCK_SCSI_DONE(flags);
3799 scp->scsi_done(scp);
3800 GDTH_UNLOCK_SCSI_DONE(flags);
3801#endif
3802 }
3803
3804#ifdef INT_COAL
3805 if (coalesced) {
3806
3807 ++pcs;
3808#ifdef GDTH_STATISTICS
3809 ++act_int_coal;
3810 if (act_int_coal > max_int_coal) {
3811 max_int_coal = act_int_coal;
3812 printk("GDT: max_int_coal = %d\n",(ushort)max_int_coal);
3813 }
3814#endif
3815
3816 if (pcs->status == 0)
3817
3818 next = FALSE;
3819 }
3820 } while (next);
3821
3822
3823 if (ha->type == GDT_PCIMPR && coalesced) {
3824 gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
3825 gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg);
3826 }
3827#endif
3828
3829 gdth_next(hanum);
3830#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
3831 return IRQ_HANDLED;
3832#endif
3833}
3834
3835static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
3836{
3837 register gdth_ha_str *ha;
3838 gdth_msg_str *msg;
3839 gdth_cmd_str *cmdp;
3840 unchar b, t;
3841
3842 ha = HADATA(gdth_ctr_tab[hanum]);
3843 cmdp = ha->pccb;
3844 TRACE(("gdth_sync_event() serv %d status %d\n",
3845 service,ha->status));
3846
3847 if (service == SCREENSERVICE) {
3848 msg = ha->pmsg;
3849 TRACE(("len: %d, answer: %d, ext: %d, alen: %d\n",
3850 msg->msg_len,msg->msg_answer,msg->msg_ext,msg->msg_alen));
3851 if (msg->msg_len > MSGLEN+1)
3852 msg->msg_len = MSGLEN+1;
3853 if (msg->msg_len)
3854 if (!(msg->msg_answer && msg->msg_ext)) {
3855 msg->msg_text[msg->msg_len] = '\0';
3856 printk("%s",msg->msg_text);
3857 }
3858
3859 if (msg->msg_ext && !msg->msg_answer) {
3860 while (gdth_test_busy(hanum))
3861 gdth_delay(0);
3862 cmdp->Service = SCREENSERVICE;
3863 cmdp->RequestBuffer = SCREEN_CMND;
3864 gdth_get_cmd_index(hanum);
3865 gdth_set_sema0(hanum);
3866 cmdp->OpCode = GDT_READ;
3867 cmdp->BoardNode = LOCALBOARD;
3868 cmdp->u.screen.reserved = 0;
3869 cmdp->u.screen.su.msg.msg_handle= msg->msg_handle;
3870 cmdp->u.screen.su.msg.msg_addr = ha->msg_phys;
3871 ha->cmd_offs_dpmem = 0;
3872 ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr)
3873 + sizeof(ulong64);
3874 ha->cmd_cnt = 0;
3875 gdth_copy_command(hanum);
3876 gdth_release_event(hanum);
3877 return 0;
3878 }
3879
3880 if (msg->msg_answer && msg->msg_alen) {
3881
3882 if (msg->msg_alen == 1) {
3883 msg->msg_alen = 0;
3884 msg->msg_len = 1;
3885 msg->msg_text[0] = 0;
3886 } else {
3887 msg->msg_alen -= 2;
3888 msg->msg_len = 2;
3889 msg->msg_text[0] = 1;
3890 msg->msg_text[1] = 0;
3891 }
3892 msg->msg_ext = 0;
3893 msg->msg_answer = 0;
3894 while (gdth_test_busy(hanum))
3895 gdth_delay(0);
3896 cmdp->Service = SCREENSERVICE;
3897 cmdp->RequestBuffer = SCREEN_CMND;
3898 gdth_get_cmd_index(hanum);
3899 gdth_set_sema0(hanum);
3900 cmdp->OpCode = GDT_WRITE;
3901 cmdp->BoardNode = LOCALBOARD;
3902 cmdp->u.screen.reserved = 0;
3903 cmdp->u.screen.su.msg.msg_handle= msg->msg_handle;
3904 cmdp->u.screen.su.msg.msg_addr = ha->msg_phys;
3905 ha->cmd_offs_dpmem = 0;
3906 ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr)
3907 + sizeof(ulong64);
3908 ha->cmd_cnt = 0;
3909 gdth_copy_command(hanum);
3910 gdth_release_event(hanum);
3911 return 0;
3912 }
3913 printk("\n");
3914
3915 } else {
3916#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
3917 b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
3918 t = scp->device->id;
3919#else
3920 b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
3921 t = scp->target;
3922#endif
3923 if (scp->SCp.sent_command == -1 && b != ha->virt_bus) {
3924 ha->raw[BUS_L2P(ha,b)].io_cnt[t]--;
3925 }
3926
3927 if (ha->status == S_BSY) {
3928 TRACE2(("Controller busy -> retry !\n"));
3929 if (scp->SCp.sent_command == GDT_MOUNT)
3930 scp->SCp.sent_command = GDT_CLUST_INFO;
3931
3932 return 2;
3933 }
3934#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
3935 if (scp->SCp.Status == GDTH_MAP_SG)
3936 pci_unmap_sg(ha->pdev,scp->request_buffer,
3937 scp->use_sg,scp->SCp.Message);
3938 else if (scp->SCp.Status == GDTH_MAP_SINGLE)
3939 pci_unmap_page(ha->pdev,scp->SCp.dma_handle,
3940 scp->request_bufflen,scp->SCp.Message);
3941 if (scp->SCp.buffer) {
3942 dma_addr_t addr;
3943 addr = (dma_addr_t)(ulong32)scp->SCp.buffer;
3944 if (scp->host_scribble)
3945 addr += (dma_addr_t)((ulong64)(ulong32)scp->host_scribble << 32);
3946 pci_unmap_page(ha->pdev,addr,16,PCI_DMA_FROMDEVICE);
3947 }
3948#endif
3949 if (ha->status == S_OK) {
3950 scp->SCp.Status = S_OK;
3951 scp->SCp.Message = ha->info;
3952 if (scp->SCp.sent_command != -1) {
3953 TRACE2(("gdth_sync_event(): special cmd 0x%x OK\n",
3954 scp->SCp.sent_command));
3955
3956 if (scp->SCp.sent_command == GDT_CLUST_INFO) {
3957 ha->hdr[t].cluster_type = (unchar)ha->info;
3958 if (!(ha->hdr[t].cluster_type &
3959 CLUSTER_MOUNTED)) {
3960
3961 scp->SCp.sent_command = GDT_MOUNT;
3962 if (ha->hdr[t].cluster_type &
3963 CLUSTER_RESERVED) {
3964
3965 scp->SCp.phase = -2;
3966 }
3967 } else {
3968 scp->SCp.sent_command = -1;
3969 }
3970 } else {
3971 if (scp->SCp.sent_command == GDT_MOUNT) {
3972 ha->hdr[t].cluster_type |= CLUSTER_MOUNTED;
3973 ha->hdr[t].media_changed = TRUE;
3974 } else if (scp->SCp.sent_command == GDT_UNMOUNT) {
3975 ha->hdr[t].cluster_type &= ~CLUSTER_MOUNTED;
3976 ha->hdr[t].media_changed = TRUE;
3977 }
3978 scp->SCp.sent_command = -1;
3979 }
3980
3981 scp->SCp.this_residual = HIGH_PRI;
3982 return 2;
3983 } else {
3984
3985 if (scp->cmnd[0] == RESERVE) {
3986 ha->hdr[t].cluster_type |= CLUSTER_RESERVED;
3987 } else if (scp->cmnd[0] == RELEASE) {
3988 ha->hdr[t].cluster_type &= ~CLUSTER_RESERVED;
3989 }
3990 scp->result = DID_OK << 16;
3991 scp->sense_buffer[0] = 0;
3992 }
3993 } else {
3994 scp->SCp.Status = ha->status;
3995 scp->SCp.Message = ha->info;
3996
3997 if (scp->SCp.sent_command != -1) {
3998 TRACE2(("gdth_sync_event(): special cmd 0x%x error 0x%x\n",
3999 scp->SCp.sent_command, ha->status));
4000 if (scp->SCp.sent_command == GDT_SCAN_START ||
4001 scp->SCp.sent_command == GDT_SCAN_END) {
4002 scp->SCp.sent_command = -1;
4003
4004 scp->SCp.this_residual = HIGH_PRI;
4005 return 2;
4006 }
4007 memset((char*)scp->sense_buffer,0,16);
4008 scp->sense_buffer[0] = 0x70;
4009 scp->sense_buffer[2] = NOT_READY;
4010 scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
4011 } else if (service == CACHESERVICE) {
4012 if (ha->status == S_CACHE_UNKNOWN &&
4013 (ha->hdr[t].cluster_type &
4014 CLUSTER_RESERVE_STATE) == CLUSTER_RESERVE_STATE) {
4015
4016 ha->hdr[t].cluster_type &= ~CLUSTER_RESERVED;
4017 }
4018 memset((char*)scp->sense_buffer,0,16);
4019 if (ha->status == (ushort)S_CACHE_RESERV) {
4020 scp->result = (DID_OK << 16) | (RESERVATION_CONFLICT << 1);
4021 } else {
4022 scp->sense_buffer[0] = 0x70;
4023 scp->sense_buffer[2] = NOT_READY;
4024 scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
4025 }
4026 if (scp->done != gdth_scsi_done) {
4027 ha->dvr.size = sizeof(ha->dvr.eu.sync);
4028 ha->dvr.eu.sync.ionode = hanum;
4029 ha->dvr.eu.sync.service = service;
4030 ha->dvr.eu.sync.status = ha->status;
4031 ha->dvr.eu.sync.info = ha->info;
4032 ha->dvr.eu.sync.hostdrive = t;
4033 if (ha->status >= 0x8000)
4034 gdth_store_event(ha, ES_SYNC, 0, &ha->dvr);
4035 else
4036 gdth_store_event(ha, ES_SYNC, service, &ha->dvr);
4037 }
4038 } else {
4039
4040 if (ha->status != S_RAW_SCSI || ha->info >= 0x100) {
4041 scp->result = DID_BAD_TARGET << 16;
4042 } else {
4043 scp->result = (DID_OK << 16) | ha->info;
4044 }
4045 }
4046 }
4047 if (!scp->SCp.have_data_in)
4048 scp->SCp.have_data_in++;
4049 else
4050 return 1;
4051 }
4052
4053 return 0;
4054}
4055
4056static char *async_cache_tab[] = {
4057 "\011\000\002\002\002\004\002\006\004"
4058 "GDT HA %u, service %u, async. status %u/%lu unknown",
4059 "\011\000\002\002\002\004\002\006\004"
4060 "GDT HA %u, service %u, async. status %u/%lu unknown",
4061 "\005\000\002\006\004"
4062 "GDT HA %u, Host Drive %lu not ready",
4063 "\005\000\002\006\004"
4064 "GDT HA %u, Host Drive %lu: REASSIGN not successful and/or data error on reassigned blocks. Drive may crash in the future and should be replaced",
4065 "\005\000\002\006\004"
4066 "GDT HA %u, mirror update on Host Drive %lu failed",
4067 "\005\000\002\006\004"
4068 "GDT HA %u, Mirror Drive %lu failed",
4069 "\005\000\002\006\004"
4070 "GDT HA %u, Mirror Drive %lu: REASSIGN not successful and/or data error on reassigned blocks. Drive may crash in the future and should be replaced",
4071 "\005\000\002\006\004"
4072 "GDT HA %u, Host Drive %lu write protected",
4073 "\005\000\002\006\004"
4074 "GDT HA %u, media changed in Host Drive %lu",
4075 "\005\000\002\006\004"
4076 "GDT HA %u, Host Drive %lu is offline",
4077 "\005\000\002\006\004"
4078 "GDT HA %u, media change of Mirror Drive %lu",
4079 "\005\000\002\006\004"
4080 "GDT HA %u, Mirror Drive %lu is write protected",
4081 "\005\000\002\006\004"
4082 "GDT HA %u, general error on Host Drive %lu. Please check the devices of this drive!",
4083 "\007\000\002\006\002\010\002"
4084 "GDT HA %u, Array Drive %u: Cache Drive %u failed",
4085 "\005\000\002\006\002"
4086 "GDT HA %u, Array Drive %u: FAIL state entered",
4087 "\005\000\002\006\002"
4088 "GDT HA %u, Array Drive %u: error",
4089 "\007\000\002\006\002\010\002"
4090 "GDT HA %u, Array Drive %u: failed drive replaced by Cache Drive %u",
4091 "\005\000\002\006\002"
4092 "GDT HA %u, Array Drive %u: parity build failed",
4093 "\005\000\002\006\002"
4094 "GDT HA %u, Array Drive %u: drive rebuild failed",
4095 "\005\000\002\010\002"
4096 "GDT HA %u, Test of Hot Fix %u failed",
4097 "\005\000\002\006\002"
4098 "GDT HA %u, Array Drive %u: drive build finished successfully",
4099 "\005\000\002\006\002"
4100 "GDT HA %u, Array Drive %u: drive rebuild finished successfully",
4101 "\007\000\002\006\002\010\002"
4102 "GDT HA %u, Array Drive %u: Hot Fix %u activated",
4103 "\005\000\002\006\002"
4104 "GDT HA %u, Host Drive %u: processing of i/o aborted due to serious drive error",
4105 "\005\000\002\010\002"
4106 "GDT HA %u, mirror update on Cache Drive %u completed",
4107 "\005\000\002\010\002"
4108 "GDT HA %u, mirror update on Cache Drive %lu failed",
4109 "\005\000\002\006\002"
4110 "GDT HA %u, Array Drive %u: drive rebuild started",
4111 "\005\000\002\012\001"
4112 "GDT HA %u, Fault bus %u: SHELF OK detected",
4113 "\005\000\002\012\001"
4114 "GDT HA %u, Fault bus %u: SHELF not OK detected",
4115 "\007\000\002\012\001\013\001"
4116 "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug started",
4117 "\007\000\002\012\001\013\001"
4118 "GDT HA %u, Fault bus %u, ID %u: new disk detected",
4119 "\007\000\002\012\001\013\001"
4120 "GDT HA %u, Fault bus %u, ID %u: old disk detected",
4121 "\007\000\002\012\001\013\001"
4122 "GDT HA %u, Fault bus %u, ID %u: plugging an active disk is invalid",
4123 "\007\000\002\012\001\013\001"
4124 "GDT HA %u, Fault bus %u, ID %u: invalid device detected",
4125 "\011\000\002\012\001\013\001\006\004"
4126 "GDT HA %u, Fault bus %u, ID %u: insufficient disk capacity (%lu MB required)",
4127 "\007\000\002\012\001\013\001"
4128 "GDT HA %u, Fault bus %u, ID %u: disk write protected",
4129 "\007\000\002\012\001\013\001"
4130 "GDT HA %u, Fault bus %u, ID %u: disk not available",
4131 "\007\000\002\012\001\006\004"
4132 "GDT HA %u, Fault bus %u: swap detected (%lu)",
4133 "\007\000\002\012\001\013\001"
4134 "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug finished successfully",
4135 "\007\000\002\012\001\013\001"
4136 "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug aborted due to user Hot Plug",
4137 "\007\000\002\012\001\013\001"
4138 "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug aborted",
4139 "\007\000\002\012\001\013\001"
4140 "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug for Hot Fix started",
4141 "\005\000\002\006\002"
4142 "GDT HA %u, Array Drive %u: drive build started",
4143 "\003\000\002"
4144 "GDT HA %u, DRAM parity error detected",
4145 "\005\000\002\006\002"
4146 "GDT HA %u, Mirror Drive %u: update started",
4147 "\007\000\002\006\002\010\002"
4148 "GDT HA %u, Mirror Drive %u: Hot Fix %u activated",
4149 "\005\000\002\006\002"
4150 "GDT HA %u, Array Drive %u: no matching Pool Hot Fix Drive available",
4151 "\005\000\002\006\002"
4152 "GDT HA %u, Array Drive %u: Pool Hot Fix Drive available",
4153 "\005\000\002\006\002"
4154 "GDT HA %u, Mirror Drive %u: no matching Pool Hot Fix Drive available",
4155 "\005\000\002\006\002"
4156 "GDT HA %u, Mirror Drive %u: Pool Hot Fix Drive available",
4157 "\007\000\002\012\001\013\001"
4158 "GDT HA %u, SCSI bus %u, ID %u: IGNORE_WIDE_RESIDUE message received",
4159 "\005\000\002\006\002"
4160 "GDT HA %u, Array Drive %u: expand started",
4161 "\005\000\002\006\002"
4162 "GDT HA %u, Array Drive %u: expand finished successfully",
4163 "\005\000\002\006\002"
4164 "GDT HA %u, Array Drive %u: expand failed",
4165 "\003\000\002"
4166 "GDT HA %u, CPU temperature critical",
4167 "\003\000\002"
4168 "GDT HA %u, CPU temperature OK",
4169 "\005\000\002\006\004"
4170 "GDT HA %u, Host drive %lu created",
4171 "\005\000\002\006\002"
4172 "GDT HA %u, Array Drive %u: expand restarted",
4173 "\005\000\002\006\002"
4174 "GDT HA %u, Array Drive %u: expand stopped",
4175 "\005\000\002\010\002"
4176 "GDT HA %u, Mirror Drive %u: drive build quited",
4177 "\005\000\002\006\002"
4178 "GDT HA %u, Array Drive %u: parity build quited",
4179 "\005\000\002\006\002"
4180 "GDT HA %u, Array Drive %u: drive rebuild quited",
4181 "\005\000\002\006\002"
4182 "GDT HA %u, Array Drive %u: parity verify started",
4183 "\005\000\002\006\002"
4184 "GDT HA %u, Array Drive %u: parity verify done",
4185 "\005\000\002\006\002"
4186 "GDT HA %u, Array Drive %u: parity verify failed",
4187 "\005\000\002\006\002"
4188 "GDT HA %u, Array Drive %u: parity error detected",
4189 "\005\000\002\006\002"
4190 "GDT HA %u, Array Drive %u: parity verify quited",
4191 "\005\000\002\006\002"
4192 "GDT HA %u, Host Drive %u reserved",
4193 "\005\000\002\006\002"
4194 "GDT HA %u, Host Drive %u mounted and released",
4195 "\005\000\002\006\002"
4196 "GDT HA %u, Host Drive %u released",
4197 "\003\000\002"
4198 "GDT HA %u, DRAM error detected and corrected with ECC",
4199 "\003\000\002"
4200 "GDT HA %u, Uncorrectable DRAM error detected with ECC",
4201 "\011\000\002\012\001\013\001\014\001"
4202 "GDT HA %u, SCSI bus %u, ID %u, LUN %u: reassigning block",
4203 "\005\000\002\006\002"
4204 "GDT HA %u, Host drive %u resetted locally",
4205 "\005\000\002\006\002"
4206 "GDT HA %u, Host drive %u resetted remotely",
4207 "\003\000\002"
4208 "GDT HA %u, async. status 75 unknown",
4209};
4210
4211
4212static int gdth_async_event(int hanum)
4213{
4214 gdth_ha_str *ha;
4215 gdth_cmd_str *cmdp;
4216 int cmd_index;
4217
4218 ha = HADATA(gdth_ctr_tab[hanum]);
4219 cmdp= ha->pccb;
4220 TRACE2(("gdth_async_event() ha %d serv %d\n",
4221 hanum,ha->service));
4222
4223 if (ha->service == SCREENSERVICE) {
4224 if (ha->status == MSG_REQUEST) {
4225 while (gdth_test_busy(hanum))
4226 gdth_delay(0);
4227 cmdp->Service = SCREENSERVICE;
4228 cmdp->RequestBuffer = SCREEN_CMND;
4229 cmd_index = gdth_get_cmd_index(hanum);
4230 gdth_set_sema0(hanum);
4231 cmdp->OpCode = GDT_READ;
4232 cmdp->BoardNode = LOCALBOARD;
4233 cmdp->u.screen.reserved = 0;
4234 cmdp->u.screen.su.msg.msg_handle= MSG_INV_HANDLE;
4235 cmdp->u.screen.su.msg.msg_addr = ha->msg_phys;
4236 ha->cmd_offs_dpmem = 0;
4237 ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr)
4238 + sizeof(ulong64);
4239 ha->cmd_cnt = 0;
4240 gdth_copy_command(hanum);
4241 if (ha->type == GDT_EISA)
4242 printk("[EISA slot %d] ",(ushort)ha->brd_phys);
4243 else if (ha->type == GDT_ISA)
4244 printk("[DPMEM 0x%4X] ",(ushort)ha->brd_phys);
4245 else
4246 printk("[PCI %d/%d] ",(ushort)(ha->brd_phys>>8),
4247 (ushort)((ha->brd_phys>>3)&0x1f));
4248 gdth_release_event(hanum);
4249 }
4250
4251 } else {
4252 if (ha->type == GDT_PCIMPR &&
4253 (ha->fw_vers & 0xff) >= 0x1a) {
4254 ha->dvr.size = 0;
4255 ha->dvr.eu.async.ionode = hanum;
4256 ha->dvr.eu.async.status = ha->status;
4257
4258 } else {
4259 ha->dvr.size = sizeof(ha->dvr.eu.async);
4260 ha->dvr.eu.async.ionode = hanum;
4261 ha->dvr.eu.async.service = ha->service;
4262 ha->dvr.eu.async.status = ha->status;
4263 ha->dvr.eu.async.info = ha->info;
4264 *(ulong32 *)ha->dvr.eu.async.scsi_coord = ha->info2;
4265 }
4266 gdth_store_event( ha, ES_ASYNC, ha->service, &ha->dvr );
4267 gdth_log_event( &ha->dvr, NULL );
4268
4269
4270 if (ha->service == CACHESERVICE && ha->status == 56) {
4271 TRACE2(("gdth_async_event(): new host drive %d created\n",
4272 (ushort)ha->info));
4273
4274 }
4275 }
4276 return 1;
4277}
4278
4279static void gdth_log_event(gdth_evt_data *dvr, char *buffer)
4280{
4281 gdth_stackframe stack;
4282 char *f = NULL;
4283 int i,j;
4284
4285 TRACE2(("gdth_log_event()\n"));
4286 if (dvr->size == 0) {
4287 if (buffer == NULL) {
4288 printk("Adapter %d: %s\n",dvr->eu.async.ionode,dvr->event_string);
4289 } else {
4290 sprintf(buffer,"Adapter %d: %s\n",
4291 dvr->eu.async.ionode,dvr->event_string);
4292 }
4293 } else if (dvr->eu.async.service == CACHESERVICE &&
4294 INDEX_OK(dvr->eu.async.status, async_cache_tab)) {
4295 TRACE2(("GDT: Async. event cache service, event no.: %d\n",
4296 dvr->eu.async.status));
4297
4298 f = async_cache_tab[dvr->eu.async.status];
4299
4300
4301 for (j=0,i=1; i < f[0]; i+=2) {
4302 switch (f[i+1]) {
4303 case 4:
4304 stack.b[j++] = *(ulong32*)&dvr->eu.stream[(int)f[i]];
4305 break;
4306 case 2:
4307 stack.b[j++] = *(ushort*)&dvr->eu.stream[(int)f[i]];
4308 break;
4309 case 1:
4310 stack.b[j++] = *(unchar*)&dvr->eu.stream[(int)f[i]];
4311 break;
4312 default:
4313 break;
4314 }
4315 }
4316
4317 if (buffer == NULL) {
4318 printk(&f[(int)f[0]],stack);
4319 printk("\n");
4320 } else {
4321 sprintf(buffer,&f[(int)f[0]],stack);
4322 }
4323
4324 } else {
4325 if (buffer == NULL) {
4326 printk("GDT HA %u, Unknown async. event service %d event no. %d\n",
4327 dvr->eu.async.ionode,dvr->eu.async.service,dvr->eu.async.status);
4328 } else {
4329 sprintf(buffer,"GDT HA %u, Unknown async. event service %d event no. %d",
4330 dvr->eu.async.ionode,dvr->eu.async.service,dvr->eu.async.status);
4331 }
4332 }
4333}
4334
4335#ifdef GDTH_STATISTICS
4336void gdth_timeout(ulong data)
4337{
4338 ulong32 i;
4339 Scsi_Cmnd *nscp;
4340 gdth_ha_str *ha;
4341 ulong flags;
4342 int hanum = 0;
4343
4344 ha = HADATA(gdth_ctr_tab[hanum]);
4345 GDTH_LOCK_HA(ha, flags);
4346
4347 for (act_stats=0,i=0; i<GDTH_MAXCMDS; ++i)
4348 if (ha->cmd_tab[i].cmnd != UNUSED_CMND)
4349 ++act_stats;
4350
4351 for (act_rq=0,nscp=ha->req_first; nscp; nscp=(Scsi_Cmnd*)nscp->SCp.ptr)
4352 ++act_rq;
4353
4354 TRACE2(("gdth_to(): ints %d, ios %d, act_stats %d, act_rq %d\n",
4355 act_ints, act_ios, act_stats, act_rq));
4356 act_ints = act_ios = 0;
4357
4358 gdth_timer.expires = jiffies + 30 * HZ;
4359 add_timer(&gdth_timer);
4360 GDTH_UNLOCK_HA(ha, flags);
4361}
4362#endif
4363
4364GDTH_INITFUNC(void, internal_setup(char *str,int *ints))
4365{
4366 int i, argc;
4367 char *cur_str, *argv;
4368
4369 TRACE2(("internal_setup() str %s ints[0] %d\n",
4370 str ? str:"NULL", ints ? ints[0]:0));
4371
4372
4373 if (ints) {
4374 argc = ints[0];
4375 if (argc > 0) {
4376 if (argc > MAXHA)
4377 argc = MAXHA;
4378 for (i = 0; i < argc; ++i)
4379 irq[i] = ints[i+1];
4380 }
4381 }
4382
4383
4384 argv = str;
4385 while (argv && (cur_str = strchr(argv, ':'))) {
4386 int val = 0, c = *++cur_str;
4387
4388 if (c == 'n' || c == 'N')
4389 val = 0;
4390 else if (c == 'y' || c == 'Y')
4391 val = 1;
4392 else
4393 val = (int)simple_strtoul(cur_str, NULL, 0);
4394
4395 if (!strncmp(argv, "disable:", 8))
4396 disable = val;
4397 else if (!strncmp(argv, "reserve_mode:", 13))
4398 reserve_mode = val;
4399 else if (!strncmp(argv, "reverse_scan:", 13))
4400 reverse_scan = val;
4401 else if (!strncmp(argv, "hdr_channel:", 12))
4402 hdr_channel = val;
4403 else if (!strncmp(argv, "max_ids:", 8))
4404 max_ids = val;
4405 else if (!strncmp(argv, "rescan:", 7))
4406 rescan = val;
4407 else if (!strncmp(argv, "virt_ctr:", 9))
4408 virt_ctr = val;
4409 else if (!strncmp(argv, "shared_access:", 14))
4410 shared_access = val;
4411 else if (!strncmp(argv, "probe_eisa_isa:", 15))
4412 probe_eisa_isa = val;
4413 else if (!strncmp(argv, "reserve_list:", 13)) {
4414 reserve_list[0] = val;
4415 for (i = 1; i < MAX_RES_ARGS; i++) {
4416 cur_str = strchr(cur_str, ',');
4417 if (!cur_str)
4418 break;
4419 if (!isdigit((int)*++cur_str)) {
4420 --cur_str;
4421 break;
4422 }
4423 reserve_list[i] =
4424 (int)simple_strtoul(cur_str, NULL, 0);
4425 }
4426 if (!cur_str)
4427 break;
4428 argv = ++cur_str;
4429 continue;
4430 }
4431
4432 if ((argv = strchr(argv, ',')))
4433 ++argv;
4434 }
4435}
4436
4437GDTH_INITFUNC(int, option_setup(char *str))
4438{
4439 int ints[MAXHA];
4440 char *cur = str;
4441 int i = 1;
4442
4443 TRACE2(("option_setup() str %s\n", str ? str:"NULL"));
4444
4445 while (cur && isdigit(*cur) && i <= MAXHA) {
4446 ints[i++] = simple_strtoul(cur, NULL, 0);
4447 if ((cur = strchr(cur, ',')) != NULL) cur++;
4448 }
4449
4450 ints[0] = i - 1;
4451 internal_setup(cur, ints);
4452 return 1;
4453}
4454
4455GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
4456{
4457 struct Scsi_Host *shp;
4458 gdth_pci_str pcistr[MAXHA];
4459 gdth_ha_str *ha;
4460 ulong32 isa_bios;
4461 ushort eisa_slot;
4462 int i,hanum,cnt,ctr,err;
4463 unchar b;
4464
4465
4466#ifdef DEBUG_GDTH
4467 printk("GDT: This driver contains debugging information !! Trace level = %d\n",
4468 DebugState);
4469 printk(" Destination of debugging information: ");
4470#ifdef __SERIAL__
4471#ifdef __COM2__
4472 printk("Serial port COM2\n");
4473#else
4474 printk("Serial port COM1\n");
4475#endif
4476#else
4477 printk("Console\n");
4478#endif
4479 gdth_delay(3000);
4480#endif
4481
4482 TRACE(("gdth_detect()\n"));
4483
4484 if (disable) {
4485 printk("GDT-HA: Controller driver disabled from command line !\n");
4486 return 0;
4487 }
4488
4489 printk("GDT-HA: Storage RAID Controller Driver. Version: %s \n",GDTH_VERSION_STR);
4490
4491 gdth_polling = TRUE; b = 0;
4492 gdth_clear_events();
4493
4494
4495 if (probe_eisa_isa) {
4496
4497 for (isa_bios=0xc8000UL; isa_bios<=0xd8000UL; isa_bios+=0x8000UL) {
4498 dma_addr_t scratch_dma_handle;
4499 scratch_dma_handle = 0;
4500
4501 if (gdth_ctr_count >= MAXHA)
4502 break;
4503 if (gdth_search_isa(isa_bios)) {
4504 shp = scsi_register(shtp,sizeof(gdth_ext_str));
4505 if (shp == NULL)
4506 continue;
4507
4508 ha = HADATA(shp);
4509 if (!gdth_init_isa(isa_bios,ha)) {
4510 scsi_unregister(shp);
4511 continue;
4512 }
4513#ifdef __ia64__
4514 break;
4515#else
4516
4517 printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n",
4518 isa_bios,ha->irq,ha->drq);
4519
4520 if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) {
4521 printk("GDT-ISA: Unable to allocate IRQ\n");
4522 scsi_unregister(shp);
4523 continue;
4524 }
4525 if (request_dma(ha->drq,"gdth")) {
4526 printk("GDT-ISA: Unable to allocate DMA channel\n");
4527 free_irq(ha->irq,ha);
4528 scsi_unregister(shp);
4529 continue;
4530 }
4531 set_dma_mode(ha->drq,DMA_MODE_CASCADE);
4532 enable_dma(ha->drq);
4533 shp->unchecked_isa_dma = 1;
4534 shp->irq = ha->irq;
4535 shp->dma_channel = ha->drq;
4536 hanum = gdth_ctr_count;
4537 gdth_ctr_tab[gdth_ctr_count++] = shp;
4538 gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
4539
4540 NUMDATA(shp)->hanum = (ushort)hanum;
4541 NUMDATA(shp)->busnum= 0;
4542
4543 ha->pccb = CMDDATA(shp);
4544 ha->ccb_phys = 0L;
4545#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4546 ha->pdev = NULL;
4547 ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH,
4548 &scratch_dma_handle);
4549 ha->scratch_phys = scratch_dma_handle;
4550 ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str),
4551 &scratch_dma_handle);
4552 ha->msg_phys = scratch_dma_handle;
4553#ifdef INT_COAL
4554 ha->coal_stat = (gdth_coal_status *)
4555 pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) *
4556 MAXOFFSETS, &scratch_dma_handle);
4557 ha->coal_stat_phys = scratch_dma_handle;
4558#endif
4559#else
4560 ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
4561 if (ha->pscratch)
4562 ha->scratch_phys = virt_to_bus(ha->pscratch);
4563 ha->pmsg = scsi_init_malloc(sizeof(gdth_msg_str), GFP_ATOMIC | GFP_DMA);
4564 if (ha->pmsg)
4565 ha->msg_phys = virt_to_bus(ha->pmsg);
4566#ifdef INT_COAL
4567 ha->coal_stat =
4568 scsi_init_malloc(sizeof(gdth_coal_status) * MAXOFFSETS,
4569 GFP_ATOMIC | GFP_DMA);
4570 if (ha->coal_stat)
4571 ha->coal_stat_phys = virt_to_bus(ha->coal_stat);
4572#endif
4573#endif
4574 ha->scratch_busy = FALSE;
4575 ha->req_first = NULL;
4576 ha->tid_cnt = MAX_HDRIVES;
4577 if (max_ids > 0 && max_ids < ha->tid_cnt)
4578 ha->tid_cnt = max_ids;
4579 for (i=0; i<GDTH_MAXCMDS; ++i)
4580 ha->cmd_tab[i].cmnd = UNUSED_CMND;
4581 ha->scan_mode = rescan ? 0x10 : 0;
4582
4583 if (ha->pscratch == NULL || ha->pmsg == NULL ||
4584 !gdth_search_drives(hanum)) {
4585 printk("GDT-ISA: Error during device scan\n");
4586 --gdth_ctr_count;
4587 --gdth_ctr_vcount;
4588#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4589#ifdef INT_COAL
4590 if (ha->coal_stat)
4591 pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
4592 MAXOFFSETS, ha->coal_stat,
4593 ha->coal_stat_phys);
4594#endif
4595 if (ha->pscratch)
4596 pci_free_consistent(ha->pdev, GDTH_SCRATCH,
4597 ha->pscratch, ha->scratch_phys);
4598 if (ha->pmsg)
4599 pci_free_consistent(ha->pdev, sizeof(gdth_msg_str),
4600 ha->pmsg, ha->msg_phys);
4601#else
4602#ifdef INT_COAL
4603 if (ha->coal_stat)
4604 scsi_init_free((void *)ha->coal_stat,
4605 sizeof(gdth_coal_status) * MAXOFFSETS);
4606#endif
4607 if (ha->pscratch)
4608 scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
4609 if (ha->pmsg)
4610 scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str));
4611#endif
4612 free_irq(ha->irq,ha);
4613 scsi_unregister(shp);
4614 continue;
4615 }
4616 if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
4617 hdr_channel = ha->bus_cnt;
4618 ha->virt_bus = hdr_channel;
4619
4620#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4621#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && \
4622 LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
4623 shp->highmem_io = 0;
4624#endif
4625 if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT)
4626 shp->max_cmd_len = 16;
4627#endif
4628 shp->max_id = ha->tid_cnt;
4629 shp->max_lun = MAXLUN;
4630 shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
4631 if (virt_ctr) {
4632 virt_ctr = 1;
4633
4634 for (b = 1; b < ha->bus_cnt + 1; ++b) {
4635 shp = scsi_register(shtp,sizeof(gdth_num_str));
4636 shp->unchecked_isa_dma = 1;
4637 shp->irq = ha->irq;
4638 shp->dma_channel = ha->drq;
4639 gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
4640 NUMDATA(shp)->hanum = (ushort)hanum;
4641 NUMDATA(shp)->busnum = b;
4642 }
4643 }
4644
4645 GDTH_INIT_LOCK_HA(ha);
4646 gdth_enable_int(hanum);
4647#endif
4648 }
4649 }
4650
4651
4652 for (eisa_slot=0x1000; eisa_slot<=0x8000; eisa_slot+=0x1000) {
4653 dma_addr_t scratch_dma_handle;
4654 scratch_dma_handle = 0;
4655
4656 if (gdth_ctr_count >= MAXHA)
4657 break;
4658 if (gdth_search_eisa(eisa_slot)) {
4659 shp = scsi_register(shtp,sizeof(gdth_ext_str));
4660 if (shp == NULL)
4661 continue;
4662
4663 ha = HADATA(shp);
4664 if (!gdth_init_eisa(eisa_slot,ha)) {
4665 scsi_unregister(shp);
4666 continue;
4667 }
4668
4669 printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n",
4670 eisa_slot>>12,ha->irq);
4671
4672 if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) {
4673 printk("GDT-EISA: Unable to allocate IRQ\n");
4674 scsi_unregister(shp);
4675 continue;
4676 }
4677 shp->unchecked_isa_dma = 0;
4678 shp->irq = ha->irq;
4679 shp->dma_channel = 0xff;
4680 hanum = gdth_ctr_count;
4681 gdth_ctr_tab[gdth_ctr_count++] = shp;
4682 gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
4683
4684 NUMDATA(shp)->hanum = (ushort)hanum;
4685 NUMDATA(shp)->busnum= 0;
4686 TRACE2(("EISA detect Bus 0: hanum %d\n",
4687 NUMDATA(shp)->hanum));
4688
4689 ha->pccb = CMDDATA(shp);
4690 ha->ccb_phys = 0L;
4691#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4692 ha->pdev = NULL;
4693 ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH,
4694 &scratch_dma_handle);
4695 ha->scratch_phys = scratch_dma_handle;
4696 ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str),
4697 &scratch_dma_handle);
4698 ha->msg_phys = scratch_dma_handle;
4699#ifdef INT_COAL
4700 ha->coal_stat = (gdth_coal_status *)
4701 pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) *
4702 MAXOFFSETS, &scratch_dma_handle);
4703 ha->coal_stat_phys = scratch_dma_handle;
4704#endif
4705 ha->ccb_phys =
4706 pci_map_single(ha->pdev,ha->pccb,
4707 sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
4708#else
4709 ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
4710 if (ha->pscratch)
4711 ha->scratch_phys = virt_to_bus(ha->pscratch);
4712 ha->pmsg = scsi_init_malloc(sizeof(gdth_msg_str), GFP_ATOMIC | GFP_DMA);
4713 if (ha->pmsg)
4714 ha->msg_phys = virt_to_bus(ha->pmsg);
4715#ifdef INT_COAL
4716 ha->coal_stat =
4717 scsi_init_malloc(sizeof(gdth_coal_status) * MAXOFFSETS,
4718 GFP_ATOMIC | GFP_DMA);
4719 if (ha->coal_stat)
4720 ha->coal_stat_phys = virt_to_bus(ha->coal_stat);
4721#endif
4722 ha->ccb_phys = virt_to_bus(ha->pccb);
4723#endif
4724 ha->scratch_busy = FALSE;
4725 ha->req_first = NULL;
4726 ha->tid_cnt = MAX_HDRIVES;
4727 if (max_ids > 0 && max_ids < ha->tid_cnt)
4728 ha->tid_cnt = max_ids;
4729 for (i=0; i<GDTH_MAXCMDS; ++i)
4730 ha->cmd_tab[i].cmnd = UNUSED_CMND;
4731 ha->scan_mode = rescan ? 0x10 : 0;
4732
4733 if (ha->pscratch == NULL || ha->pmsg == NULL ||
4734 !gdth_search_drives(hanum)) {
4735 printk("GDT-EISA: Error during device scan\n");
4736 --gdth_ctr_count;
4737 --gdth_ctr_vcount;
4738#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4739#ifdef INT_COAL
4740 if (ha->coal_stat)
4741 pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
4742 MAXOFFSETS, ha->coal_stat,
4743 ha->coal_stat_phys);
4744#endif
4745 if (ha->pscratch)
4746 pci_free_consistent(ha->pdev, GDTH_SCRATCH,
4747 ha->pscratch, ha->scratch_phys);
4748 if (ha->pmsg)
4749 pci_free_consistent(ha->pdev, sizeof(gdth_msg_str),
4750 ha->pmsg, ha->msg_phys);
4751 if (ha->ccb_phys)
4752 pci_unmap_single(ha->pdev,ha->ccb_phys,
4753 sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
4754#else
4755#ifdef INT_COAL
4756 if (ha->coal_stat)
4757 scsi_init_free((void *)ha->coal_stat,
4758 sizeof(gdth_coal_status) * MAXOFFSETS);
4759#endif
4760 if (ha->pscratch)
4761 scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
4762 if (ha->pmsg)
4763 scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str));
4764#endif
4765 free_irq(ha->irq,ha);
4766 scsi_unregister(shp);
4767 continue;
4768 }
4769 if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
4770 hdr_channel = ha->bus_cnt;
4771 ha->virt_bus = hdr_channel;
4772
4773#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4774#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && \
4775 LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
4776 shp->highmem_io = 0;
4777#endif
4778 if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT)
4779 shp->max_cmd_len = 16;
4780#endif
4781 shp->max_id = ha->tid_cnt;
4782 shp->max_lun = MAXLUN;
4783 shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
4784 if (virt_ctr) {
4785 virt_ctr = 1;
4786
4787 for (b = 1; b < ha->bus_cnt + 1; ++b) {
4788 shp = scsi_register(shtp,sizeof(gdth_num_str));
4789 shp->unchecked_isa_dma = 0;
4790 shp->irq = ha->irq;
4791 shp->dma_channel = 0xff;
4792 gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
4793 NUMDATA(shp)->hanum = (ushort)hanum;
4794 NUMDATA(shp)->busnum = b;
4795 }
4796 }
4797
4798 GDTH_INIT_LOCK_HA(ha);
4799 gdth_enable_int(hanum);
4800 }
4801 }
4802 }
4803
4804
4805 cnt = gdth_search_pci(pcistr);
4806 printk("GDT-HA: Found %d PCI Storage RAID Controllers\n",cnt);
4807 gdth_sort_pci(pcistr,cnt);
4808 for (ctr = 0; ctr < cnt; ++ctr) {
4809 dma_addr_t scratch_dma_handle;
4810 scratch_dma_handle = 0;
4811
4812 if (gdth_ctr_count >= MAXHA)
4813 break;
4814 shp = scsi_register(shtp,sizeof(gdth_ext_str));
4815 if (shp == NULL)
4816 continue;
4817
4818 ha = HADATA(shp);
4819 if (!gdth_init_pci(&pcistr[ctr],ha)) {
4820 scsi_unregister(shp);
4821 continue;
4822 }
4823
4824 printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n",
4825 pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq);
4826
4827 if (request_irq(ha->irq, gdth_interrupt,
4828 SA_INTERRUPT|SA_SHIRQ, "gdth", ha))
4829 {
4830 printk("GDT-PCI: Unable to allocate IRQ\n");
4831 scsi_unregister(shp);
4832 continue;
4833 }
4834 shp->unchecked_isa_dma = 0;
4835 shp->irq = ha->irq;
4836 shp->dma_channel = 0xff;
4837 hanum = gdth_ctr_count;
4838 gdth_ctr_tab[gdth_ctr_count++] = shp;
4839 gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
4840
4841 NUMDATA(shp)->hanum = (ushort)hanum;
4842 NUMDATA(shp)->busnum= 0;
4843
4844 ha->pccb = CMDDATA(shp);
4845 ha->ccb_phys = 0L;
4846#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4847 ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH,
4848 &scratch_dma_handle);
4849 ha->scratch_phys = scratch_dma_handle;
4850 ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str),
4851 &scratch_dma_handle);
4852 ha->msg_phys = scratch_dma_handle;
4853#ifdef INT_COAL
4854 ha->coal_stat = (gdth_coal_status *)
4855 pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) *
4856 MAXOFFSETS, &scratch_dma_handle);
4857 ha->coal_stat_phys = scratch_dma_handle;
4858#endif
4859#else
4860 ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
4861 if (ha->pscratch)
4862 ha->scratch_phys = virt_to_bus(ha->pscratch);
4863 ha->pmsg = scsi_init_malloc(sizeof(gdth_msg_str), GFP_ATOMIC | GFP_DMA);
4864 if (ha->pmsg)
4865 ha->msg_phys = virt_to_bus(ha->pmsg);
4866#ifdef INT_COAL
4867 ha->coal_stat =
4868 scsi_init_malloc(sizeof(gdth_coal_status) * MAXOFFSETS,
4869 GFP_ATOMIC | GFP_DMA);
4870 if (ha->coal_stat)
4871 ha->coal_stat_phys = virt_to_bus(ha->coal_stat);
4872#endif
4873#endif
4874 ha->scratch_busy = FALSE;
4875 ha->req_first = NULL;
4876 ha->tid_cnt = pcistr[ctr].device_id >= 0x200 ? MAXID : MAX_HDRIVES;
4877 if (max_ids > 0 && max_ids < ha->tid_cnt)
4878 ha->tid_cnt = max_ids;
4879 for (i=0; i<GDTH_MAXCMDS; ++i)
4880 ha->cmd_tab[i].cmnd = UNUSED_CMND;
4881 ha->scan_mode = rescan ? 0x10 : 0;
4882
4883 err = FALSE;
4884 if (ha->pscratch == NULL || ha->pmsg == NULL ||
4885 !gdth_search_drives(hanum)) {
4886 err = TRUE;
4887 } else {
4888 if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
4889 hdr_channel = ha->bus_cnt;
4890 ha->virt_bus = hdr_channel;
4891
4892#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4893#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
4894 scsi_set_device(shp, &pcistr[ctr].pdev->dev);
4895#else
4896 scsi_set_pci_device(shp, pcistr[ctr].pdev);
4897#endif
4898 if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat &GDT_64BIT)||
4899
4900 (!ha->dma64_support)) {
4901 if (pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffff)) {
4902 printk(KERN_WARNING "GDT-PCI %d: Unable to set 32-bit DMA\n", hanum);
4903 err = TRUE;
4904 }
4905 } else {
4906 shp->max_cmd_len = 16;
4907 if (!pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffffffffffffULL)) {
4908 printk("GDT-PCI %d: 64-bit DMA enabled\n", hanum);
4909 } else if (pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffff)) {
4910 printk(KERN_WARNING "GDT-PCI %d: Unable to set 64/32-bit DMA\n", hanum);
4911 err = TRUE;
4912 }
4913 }
4914#endif
4915 }
4916
4917 if (err) {
4918 printk("GDT-PCI %d: Error during device scan\n", hanum);
4919 --gdth_ctr_count;
4920 --gdth_ctr_vcount;
4921#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4922#ifdef INT_COAL
4923 if (ha->coal_stat)
4924 pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
4925 MAXOFFSETS, ha->coal_stat,
4926 ha->coal_stat_phys);
4927#endif
4928 if (ha->pscratch)
4929 pci_free_consistent(ha->pdev, GDTH_SCRATCH,
4930 ha->pscratch, ha->scratch_phys);
4931 if (ha->pmsg)
4932 pci_free_consistent(ha->pdev, sizeof(gdth_msg_str),
4933 ha->pmsg, ha->msg_phys);
4934#else
4935#ifdef INT_COAL
4936 if (ha->coal_stat)
4937 scsi_init_free((void *)ha->coal_stat,
4938 sizeof(gdth_coal_status) * MAXOFFSETS);
4939#endif
4940 if (ha->pscratch)
4941 scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
4942 if (ha->pmsg)
4943 scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str));
4944#endif
4945 free_irq(ha->irq,ha);
4946 scsi_unregister(shp);
4947 continue;
4948 }
4949
4950 shp->max_id = ha->tid_cnt;
4951 shp->max_lun = MAXLUN;
4952 shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
4953 if (virt_ctr) {
4954 virt_ctr = 1;
4955
4956 for (b = 1; b < ha->bus_cnt + 1; ++b) {
4957 shp = scsi_register(shtp,sizeof(gdth_num_str));
4958 shp->unchecked_isa_dma = 0;
4959 shp->irq = ha->irq;
4960 shp->dma_channel = 0xff;
4961 gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
4962 NUMDATA(shp)->hanum = (ushort)hanum;
4963 NUMDATA(shp)->busnum = b;
4964 }
4965 }
4966
4967
4968 GDTH_INIT_LOCK_HA(ha);
4969 gdth_enable_int(hanum);
4970 }
4971
4972 TRACE2(("gdth_detect() %d controller detected\n",gdth_ctr_count));
4973 if (gdth_ctr_count > 0) {
4974#ifdef GDTH_STATISTICS
4975 TRACE2(("gdth_detect(): Initializing timer !\n"));
4976 init_timer(&gdth_timer);
4977 gdth_timer.expires = jiffies + HZ;
4978 gdth_timer.data = 0L;
4979 gdth_timer.function = gdth_timeout;
4980 add_timer(&gdth_timer);
4981#endif
4982 major = register_chrdev(0,"gdth",&gdth_fops);
4983 register_reboot_notifier(&gdth_notifier);
4984 }
4985 gdth_polling = FALSE;
4986 return gdth_ctr_vcount;
4987}
4988
4989
4990int gdth_release(struct Scsi_Host *shp)
4991{
4992 int hanum;
4993 gdth_ha_str *ha;
4994
4995 TRACE2(("gdth_release()\n"));
4996 if (NUMDATA(shp)->busnum == 0) {
4997 hanum = NUMDATA(shp)->hanum;
4998 ha = HADATA(gdth_ctr_tab[hanum]);
4999#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5000 if (ha->sdev) {
5001 scsi_free_host_dev(ha->sdev);
5002 ha->sdev = NULL;
5003 }
5004#endif
5005 gdth_flush(hanum);
5006
5007 if (shp->irq) {
5008 free_irq(shp->irq,ha);
5009 }
5010#ifndef __ia64__
5011 if (shp->dma_channel != 0xff) {
5012 free_dma(shp->dma_channel);
5013 }
5014#endif
5015#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5016#ifdef INT_COAL
5017 if (ha->coal_stat)
5018 pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
5019 MAXOFFSETS, ha->coal_stat, ha->coal_stat_phys);
5020#endif
5021 if (ha->pscratch)
5022 pci_free_consistent(ha->pdev, GDTH_SCRATCH,
5023 ha->pscratch, ha->scratch_phys);
5024 if (ha->pmsg)
5025 pci_free_consistent(ha->pdev, sizeof(gdth_msg_str),
5026 ha->pmsg, ha->msg_phys);
5027 if (ha->ccb_phys)
5028 pci_unmap_single(ha->pdev,ha->ccb_phys,
5029 sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
5030#else
5031#ifdef INT_COAL
5032 if (ha->coal_stat)
5033 scsi_init_free((void *)ha->coal_stat,
5034 sizeof(gdth_coal_status) * MAXOFFSETS);
5035#endif
5036 if (ha->pscratch)
5037 scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
5038 if (ha->pmsg)
5039 scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str));
5040#endif
5041 gdth_ctr_released++;
5042 TRACE2(("gdth_release(): HA %d of %d\n",
5043 gdth_ctr_released, gdth_ctr_count));
5044
5045 if (gdth_ctr_released == gdth_ctr_count) {
5046#ifdef GDTH_STATISTICS
5047 del_timer(&gdth_timer);
5048#endif
5049 unregister_chrdev(major,"gdth");
5050 unregister_reboot_notifier(&gdth_notifier);
5051 }
5052 }
5053
5054 scsi_unregister(shp);
5055 return 0;
5056}
5057
5058
5059static const char *gdth_ctr_name(int hanum)
5060{
5061 gdth_ha_str *ha;
5062
5063 TRACE2(("gdth_ctr_name()\n"));
5064
5065 ha = HADATA(gdth_ctr_tab[hanum]);
5066
5067 if (ha->type == GDT_EISA) {
5068 switch (ha->stype) {
5069 case GDT3_ID:
5070 return("GDT3000/3020");
5071 case GDT3A_ID:
5072 return("GDT3000A/3020A/3050A");
5073 case GDT3B_ID:
5074 return("GDT3000B/3010A");
5075 }
5076 } else if (ha->type == GDT_ISA) {
5077 return("GDT2000/2020");
5078 } else if (ha->type == GDT_PCI) {
5079 switch (ha->stype) {
5080 case PCI_DEVICE_ID_VORTEX_GDT60x0:
5081 return("GDT6000/6020/6050");
5082 case PCI_DEVICE_ID_VORTEX_GDT6000B:
5083 return("GDT6000B/6010");
5084 }
5085 }
5086
5087
5088 return("");
5089}
5090
5091const char *gdth_info(struct Scsi_Host *shp)
5092{
5093 int hanum;
5094 gdth_ha_str *ha;
5095
5096 TRACE2(("gdth_info()\n"));
5097 hanum = NUMDATA(shp)->hanum;
5098 ha = HADATA(gdth_ctr_tab[hanum]);
5099
5100 return ((const char *)ha->binfo.type_string);
5101}
5102
5103#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
5104
5105int gdth_abort(Scsi_Cmnd *scp)
5106{
5107 TRACE2(("gdth_abort() reason %d\n",scp->abort_reason));
5108 return SCSI_ABORT_SNOOZE;
5109}
5110
5111int gdth_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
5112{
5113 TRACE2(("gdth_reset()\n"));
5114 return SCSI_RESET_PUNT;
5115}
5116#endif
5117
5118
5119int gdth_eh_abort(Scsi_Cmnd *scp)
5120{
5121 TRACE2(("gdth_eh_abort()\n"));
5122 return FAILED;
5123}
5124
5125int gdth_eh_device_reset(Scsi_Cmnd *scp)
5126{
5127 TRACE2(("gdth_eh_device_reset()\n"));
5128 return FAILED;
5129}
5130
5131int gdth_eh_bus_reset(Scsi_Cmnd *scp)
5132{
5133 int i, hanum;
5134 gdth_ha_str *ha;
5135 ulong flags;
5136 Scsi_Cmnd *cmnd;
5137 unchar b;
5138
5139 TRACE2(("gdth_eh_bus_reset()\n"));
5140#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5141 hanum = NUMDATA(scp->device->host)->hanum;
5142 b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
5143#else
5144 hanum = NUMDATA(scp->host)->hanum;
5145 b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
5146#endif
5147 ha = HADATA(gdth_ctr_tab[hanum]);
5148
5149
5150 GDTH_LOCK_HA(ha, flags);
5151 for (i = 0; i < GDTH_MAXCMDS; ++i) {
5152 cmnd = ha->cmd_tab[i].cmnd;
5153#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5154 if (!SPECIAL_SCP(cmnd) && cmnd->device->channel == b)
5155#else
5156 if (!SPECIAL_SCP(cmnd) && cmnd->channel == b)
5157#endif
5158 ha->cmd_tab[i].cmnd = UNUSED_CMND;
5159 }
5160 GDTH_UNLOCK_HA(ha, flags);
5161
5162 if (b == ha->virt_bus) {
5163
5164 for (i = 0; i < MAX_HDRIVES; ++i) {
5165 if (ha->hdr[i].present) {
5166 GDTH_LOCK_HA(ha, flags);
5167 gdth_polling = TRUE;
5168 while (gdth_test_busy(hanum))
5169 gdth_delay(0);
5170 if (gdth_internal_cmd(hanum, CACHESERVICE,
5171 GDT_CLUST_RESET, i, 0, 0))
5172 ha->hdr[i].cluster_type &= ~CLUSTER_RESERVED;
5173 gdth_polling = FALSE;
5174 GDTH_UNLOCK_HA(ha, flags);
5175 }
5176 }
5177 } else {
5178
5179 GDTH_LOCK_HA(ha, flags);
5180 for (i = 0; i < MAXID; ++i)
5181 ha->raw[BUS_L2P(ha,b)].io_cnt[i] = 0;
5182 gdth_polling = TRUE;
5183 while (gdth_test_busy(hanum))
5184 gdth_delay(0);
5185 gdth_internal_cmd(hanum, SCSIRAWSERVICE, GDT_RESET_BUS,
5186 BUS_L2P(ha,b), 0, 0);
5187 gdth_polling = FALSE;
5188 GDTH_UNLOCK_HA(ha, flags);
5189 }
5190 return SUCCESS;
5191}
5192
5193int gdth_eh_host_reset(Scsi_Cmnd *scp)
5194{
5195 TRACE2(("gdth_eh_host_reset()\n"));
5196 return FAILED;
5197}
5198
5199
5200#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5201int gdth_bios_param(struct scsi_device *sdev,struct block_device *bdev,sector_t cap,int *ip)
5202#else
5203int gdth_bios_param(Disk *disk,kdev_t dev,int *ip)
5204#endif
5205{
5206 unchar b, t;
5207 int hanum;
5208 gdth_ha_str *ha;
5209 struct scsi_device *sd;
5210 unsigned capacity;
5211
5212#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5213 sd = sdev;
5214 capacity = cap;
5215#else
5216 sd = disk->device;
5217 capacity = disk->capacity;
5218#endif
5219 hanum = NUMDATA(sd->host)->hanum;
5220 b = virt_ctr ? NUMDATA(sd->host)->busnum : sd->channel;
5221 t = sd->id;
5222 TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", hanum, b, t));
5223 ha = HADATA(gdth_ctr_tab[hanum]);
5224
5225 if (b != ha->virt_bus || ha->hdr[t].heads == 0) {
5226
5227 TRACE2(("Evaluate mapping\n"));
5228 gdth_eval_mapping(capacity,&ip[2],&ip[0],&ip[1]);
5229 } else {
5230 ip[0] = ha->hdr[t].heads;
5231 ip[1] = ha->hdr[t].secs;
5232 ip[2] = capacity / ip[0] / ip[1];
5233 }
5234
5235 TRACE2(("gdth_bios_param(): %d heads, %d secs, %d cyls\n",
5236 ip[0],ip[1],ip[2]));
5237 return 0;
5238}
5239
5240
5241int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *))
5242{
5243 int hanum;
5244 int priority;
5245
5246 TRACE(("gdth_queuecommand() cmd 0x%x\n", scp->cmnd[0]));
5247
5248 scp->scsi_done = (void *)done;
5249 scp->SCp.have_data_in = 1;
5250 scp->SCp.phase = -1;
5251 scp->SCp.sent_command = -1;
5252 scp->SCp.Status = GDTH_MAP_NONE;
5253 scp->SCp.buffer = (struct scatterlist *)NULL;
5254#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5255 hanum = NUMDATA(scp->device->host)->hanum;
5256#else
5257 hanum = NUMDATA(scp->host)->hanum;
5258#endif
5259#ifdef GDTH_STATISTICS
5260 ++act_ios;
5261#endif
5262
5263 priority = DEFAULT_PRI;
5264 if (scp->done == gdth_scsi_done)
5265 priority = scp->SCp.this_residual;
5266 gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6);
5267 gdth_putq( hanum, scp, priority );
5268 gdth_next( hanum );
5269 return 0;
5270}
5271
5272
5273static int gdth_open(struct inode *inode, struct file *filep)
5274{
5275#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5276 gdth_ha_str *ha;
5277 int i;
5278
5279 for (i = 0; i < gdth_ctr_count; i++) {
5280 ha = HADATA(gdth_ctr_tab[i]);
5281 if (!ha->sdev)
5282 ha->sdev = scsi_get_host_dev(gdth_ctr_tab[i]);
5283 }
5284#endif
5285
5286 TRACE(("gdth_open()\n"));
5287 return 0;
5288}
5289
5290static int gdth_close(struct inode *inode, struct file *filep)
5291{
5292 TRACE(("gdth_close()\n"));
5293 return 0;
5294}
5295
5296static int ioc_event(unsigned long arg)
5297{
5298 gdth_ioctl_event evt;
5299 gdth_ha_str *ha;
5300 ulong flags;
5301
5302 if (copy_from_user(&evt, (char *)arg, sizeof(gdth_ioctl_event)) ||
5303 evt.ionode >= gdth_ctr_count)
5304 return -EFAULT;
5305 ha = HADATA(gdth_ctr_tab[evt.ionode]);
5306
5307 if (evt.erase == 0xff) {
5308 if (evt.event.event_source == ES_TEST)
5309 evt.event.event_data.size=sizeof(evt.event.event_data.eu.test);
5310 else if (evt.event.event_source == ES_DRIVER)
5311 evt.event.event_data.size=sizeof(evt.event.event_data.eu.driver);
5312 else if (evt.event.event_source == ES_SYNC)
5313 evt.event.event_data.size=sizeof(evt.event.event_data.eu.sync);
5314 else
5315 evt.event.event_data.size=sizeof(evt.event.event_data.eu.async);
5316 GDTH_LOCK_HA(ha, flags);
5317 gdth_store_event(ha, evt.event.event_source, evt.event.event_idx,
5318 &evt.event.event_data);
5319 GDTH_UNLOCK_HA(ha, flags);
5320 } else if (evt.erase == 0xfe) {
5321 gdth_clear_events();
5322 } else if (evt.erase == 0) {
5323 evt.handle = gdth_read_event(ha, evt.handle, &evt.event);
5324 } else {
5325 gdth_readapp_event(ha, evt.erase, &evt.event);
5326 }
5327 if (copy_to_user((char *)arg, &evt, sizeof(gdth_ioctl_event)))
5328 return -EFAULT;
5329 return 0;
5330}
5331
5332static int ioc_lockdrv(unsigned long arg)
5333{
5334 gdth_ioctl_lockdrv ldrv;
5335 unchar i, j;
5336 ulong flags;
5337 gdth_ha_str *ha;
5338
5339 if (copy_from_user(&ldrv, (char *)arg, sizeof(gdth_ioctl_lockdrv)) ||
5340 ldrv.ionode >= gdth_ctr_count)
5341 return -EFAULT;
5342 ha = HADATA(gdth_ctr_tab[ldrv.ionode]);
5343
5344 for (i = 0; i < ldrv.drive_cnt && i < MAX_HDRIVES; ++i) {
5345 j = ldrv.drives[i];
5346 if (j >= MAX_HDRIVES || !ha->hdr[j].present)
5347 continue;
5348 if (ldrv.lock) {
5349 GDTH_LOCK_HA(ha, flags);
5350 ha->hdr[j].lock = 1;
5351 GDTH_UNLOCK_HA(ha, flags);
5352 gdth_wait_completion(ldrv.ionode, ha->bus_cnt, j);
5353 gdth_stop_timeout(ldrv.ionode, ha->bus_cnt, j);
5354 } else {
5355 GDTH_LOCK_HA(ha, flags);
5356 ha->hdr[j].lock = 0;
5357 GDTH_UNLOCK_HA(ha, flags);
5358 gdth_start_timeout(ldrv.ionode, ha->bus_cnt, j);
5359 gdth_next(ldrv.ionode);
5360 }
5361 }
5362 return 0;
5363}
5364
5365static int ioc_resetdrv(unsigned long arg, char *cmnd)
5366{
5367 gdth_ioctl_reset res;
5368 gdth_cmd_str cmd;
5369 int hanum;
5370 gdth_ha_str *ha;
5371#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5372 Scsi_Request *srp;
5373#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5374 Scsi_Cmnd *scp;
5375#else
5376 Scsi_Cmnd scp;
5377#endif
5378
5379 if (copy_from_user(&res, (char *)arg, sizeof(gdth_ioctl_reset)) ||
5380 res.ionode >= gdth_ctr_count || res.number >= MAX_HDRIVES)
5381 return -EFAULT;
5382 hanum = res.ionode;
5383 ha = HADATA(gdth_ctr_tab[hanum]);
5384
5385 if (!ha->hdr[res.number].present)
5386 return 0;
5387 memset(&cmd, 0, sizeof(gdth_cmd_str));
5388 cmd.Service = CACHESERVICE;
5389 cmd.OpCode = GDT_CLUST_RESET;
5390 if (ha->cache_feat & GDT_64BIT)
5391 cmd.u.cache64.DeviceNo = res.number;
5392 else
5393 cmd.u.cache.DeviceNo = res.number;
5394#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5395 srp = scsi_allocate_request(ha->sdev, GFP_KERNEL);
5396 if (!srp)
5397 return -ENOMEM;
5398 srp->sr_cmd_len = 12;
5399 srp->sr_use_sg = 0;
5400 gdth_do_req(srp, &cmd, cmnd, 30);
5401 res.status = (ushort)srp->sr_command->SCp.Status;
5402 scsi_release_request(srp);
5403#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5404 scp = scsi_allocate_device(ha->sdev, 1, FALSE);
5405 if (!scp)
5406 return -ENOMEM;
5407 scp->cmd_len = 12;
5408 scp->use_sg = 0;
5409 gdth_do_cmd(scp, &cmd, cmnd, 30);
5410 res.status = (ushort)scp->SCp.Status;
5411 scsi_release_command(scp);
5412#else
5413 memset(&ha->sdev,0,sizeof(Scsi_Device));
5414 memset(&scp, 0,sizeof(Scsi_Cmnd));
5415 ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
5416 ha->sdev.id = scp.target = ha->sdev.host->this_id;
5417 scp.device = &ha->sdev;
5418 gdth_do_cmd(&scp, &cmd, cmnd, 30);
5419 res.status = (ushort)scp.SCp.Status;
5420#endif
5421 if (copy_to_user((char *)arg, &res, sizeof(gdth_ioctl_reset)))
5422 return -EFAULT;
5423 return 0;
5424}
5425
5426static int ioc_general(unsigned long arg, char *cmnd)
5427{
5428 gdth_ioctl_general gen;
5429 char *buf = NULL;
5430 ulong64 paddr;
5431 int hanum;
5432 gdth_ha_str *ha;
5433#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5434 Scsi_Request *srp;
5435#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5436 Scsi_Cmnd *scp;
5437#else
5438 Scsi_Cmnd scp;
5439#endif
5440
5441 if (copy_from_user(&gen, (char *)arg, sizeof(gdth_ioctl_general)) ||
5442 gen.ionode >= gdth_ctr_count)
5443 return -EFAULT;
5444 hanum = gen.ionode;
5445 ha = HADATA(gdth_ctr_tab[hanum]);
5446 if (gen.data_len + gen.sense_len != 0) {
5447 if (!(buf = gdth_ioctl_alloc(hanum, gen.data_len + gen.sense_len,
5448 FALSE, &paddr)))
5449 return -EFAULT;
5450 if (copy_from_user(buf, (char *)arg + sizeof(gdth_ioctl_general),
5451 gen.data_len + gen.sense_len)) {
5452 gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
5453 return -EFAULT;
5454 }
5455
5456 if (gen.command.OpCode == GDT_IOCTL) {
5457 gen.command.u.ioctl.p_param = paddr;
5458 } else if (gen.command.Service == CACHESERVICE) {
5459 if (ha->cache_feat & GDT_64BIT) {
5460
5461 gen.command.u.cache64.BlockCnt = gen.command.u.cache.BlockCnt;
5462 gen.command.u.cache64.BlockNo = gen.command.u.cache.BlockNo;
5463 gen.command.u.cache64.DeviceNo = gen.command.u.cache.DeviceNo;
5464
5465 if (ha->cache_feat & SCATTER_GATHER) {
5466 gen.command.u.cache64.DestAddr = (ulong64)-1;
5467 gen.command.u.cache64.sg_canz = 1;
5468 gen.command.u.cache64.sg_lst[0].sg_ptr = paddr;
5469 gen.command.u.cache64.sg_lst[0].sg_len = gen.data_len;
5470 gen.command.u.cache64.sg_lst[1].sg_len = 0;
5471 } else {
5472 gen.command.u.cache64.DestAddr = paddr;
5473 gen.command.u.cache64.sg_canz = 0;
5474 }
5475 } else {
5476 if (ha->cache_feat & SCATTER_GATHER) {
5477 gen.command.u.cache.DestAddr = 0xffffffff;
5478 gen.command.u.cache.sg_canz = 1;
5479 gen.command.u.cache.sg_lst[0].sg_ptr = (ulong32)paddr;
5480 gen.command.u.cache.sg_lst[0].sg_len = gen.data_len;
5481 gen.command.u.cache.sg_lst[1].sg_len = 0;
5482 } else {
5483 gen.command.u.cache.DestAddr = paddr;
5484 gen.command.u.cache.sg_canz = 0;
5485 }
5486 }
5487 } else if (gen.command.Service == SCSIRAWSERVICE) {
5488 if (ha->raw_feat & GDT_64BIT) {
5489
5490 char cmd[16];
5491 gen.command.u.raw64.sense_len = gen.command.u.raw.sense_len;
5492 gen.command.u.raw64.bus = gen.command.u.raw.bus;
5493 gen.command.u.raw64.lun = gen.command.u.raw.lun;
5494 gen.command.u.raw64.target = gen.command.u.raw.target;
5495 memcpy(cmd, gen.command.u.raw.cmd, 16);
5496 memcpy(gen.command.u.raw64.cmd, cmd, 16);
5497 gen.command.u.raw64.clen = gen.command.u.raw.clen;
5498 gen.command.u.raw64.sdlen = gen.command.u.raw.sdlen;
5499 gen.command.u.raw64.direction = gen.command.u.raw.direction;
5500
5501 if (ha->raw_feat & SCATTER_GATHER) {
5502 gen.command.u.raw64.sdata = (ulong64)-1;
5503 gen.command.u.raw64.sg_ranz = 1;
5504 gen.command.u.raw64.sg_lst[0].sg_ptr = paddr;
5505 gen.command.u.raw64.sg_lst[0].sg_len = gen.data_len;
5506 gen.command.u.raw64.sg_lst[1].sg_len = 0;
5507 } else {
5508 gen.command.u.raw64.sdata = paddr;
5509 gen.command.u.raw64.sg_ranz = 0;
5510 }
5511 gen.command.u.raw64.sense_data = paddr + gen.data_len;
5512 } else {
5513 if (ha->raw_feat & SCATTER_GATHER) {
5514 gen.command.u.raw.sdata = 0xffffffff;
5515 gen.command.u.raw.sg_ranz = 1;
5516 gen.command.u.raw.sg_lst[0].sg_ptr = (ulong32)paddr;
5517 gen.command.u.raw.sg_lst[0].sg_len = gen.data_len;
5518 gen.command.u.raw.sg_lst[1].sg_len = 0;
5519 } else {
5520 gen.command.u.raw.sdata = paddr;
5521 gen.command.u.raw.sg_ranz = 0;
5522 }
5523 gen.command.u.raw.sense_data = (ulong32)paddr + gen.data_len;
5524 }
5525 } else {
5526 gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
5527 return -EFAULT;
5528 }
5529 }
5530
5531#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5532 srp = scsi_allocate_request(ha->sdev, GFP_KERNEL);
5533 if (!srp)
5534 return -ENOMEM;
5535 srp->sr_cmd_len = 12;
5536 srp->sr_use_sg = 0;
5537 gdth_do_req(srp, &gen.command, cmnd, gen.timeout);
5538 gen.status = srp->sr_command->SCp.Status;
5539 gen.info = srp->sr_command->SCp.Message;
5540 scsi_release_request(srp);
5541#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5542 scp = scsi_allocate_device(ha->sdev, 1, FALSE);
5543 if (!scp)
5544 return -ENOMEM;
5545 scp->cmd_len = 12;
5546 scp->use_sg = 0;
5547 gdth_do_cmd(scp, &gen.command, cmnd, gen.timeout);
5548 gen.status = scp->SCp.Status;
5549 gen.info = scp->SCp.Message;
5550 scsi_release_command(scp);
5551#else
5552 memset(&ha->sdev,0,sizeof(Scsi_Device));
5553 memset(&scp, 0,sizeof(Scsi_Cmnd));
5554 ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
5555 ha->sdev.id = scp.target = ha->sdev.host->this_id;
5556 scp.device = &ha->sdev;
5557 gdth_do_cmd(&scp, &gen.command, cmnd, gen.timeout);
5558 gen.status = scp.SCp.Status;
5559 gen.info = scp.SCp.Message;
5560#endif
5561
5562 if (copy_to_user((char *)arg + sizeof(gdth_ioctl_general), buf,
5563 gen.data_len + gen.sense_len)) {
5564 gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
5565 return -EFAULT;
5566 }
5567 if (copy_to_user((char *)arg, &gen,
5568 sizeof(gdth_ioctl_general) - sizeof(gdth_cmd_str))) {
5569 gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
5570 return -EFAULT;
5571 }
5572 gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
5573 return 0;
5574}
5575
5576static int ioc_hdrlist(unsigned long arg, char *cmnd)
5577{
5578 gdth_ioctl_rescan rsc;
5579 gdth_cmd_str cmd;
5580 gdth_ha_str *ha;
5581 unchar i;
5582 int hanum;
5583#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5584 Scsi_Request *srp;
5585#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5586 Scsi_Cmnd *scp;
5587#else
5588 Scsi_Cmnd scp;
5589#endif
5590
5591 if (copy_from_user(&rsc, (char *)arg, sizeof(gdth_ioctl_rescan)) ||
5592 rsc.ionode >= gdth_ctr_count)
5593 return -EFAULT;
5594 hanum = rsc.ionode;
5595 ha = HADATA(gdth_ctr_tab[hanum]);
5596 memset(&cmd, 0, sizeof(gdth_cmd_str));
5597
5598#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5599 srp = scsi_allocate_request(ha->sdev, GFP_KERNEL);
5600 if (!srp)
5601 return -ENOMEM;
5602 srp->sr_cmd_len = 12;
5603 srp->sr_use_sg = 0;
5604#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5605 scp = scsi_allocate_device(ha->sdev, 1, FALSE);
5606 if (!scp)
5607 return -ENOMEM;
5608 scp->cmd_len = 12;
5609 scp->use_sg = 0;
5610#else
5611 memset(&ha->sdev,0,sizeof(Scsi_Device));
5612 memset(&scp, 0,sizeof(Scsi_Cmnd));
5613 ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
5614 ha->sdev.id = scp.target = ha->sdev.host->this_id;
5615 scp.device = &ha->sdev;
5616#endif
5617
5618 for (i = 0; i < MAX_HDRIVES; ++i) {
5619 if (!ha->hdr[i].present) {
5620 rsc.hdr_list[i].bus = 0xff;
5621 continue;
5622 }
5623 rsc.hdr_list[i].bus = ha->virt_bus;
5624 rsc.hdr_list[i].target = i;
5625 rsc.hdr_list[i].lun = 0;
5626 rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
5627 if (ha->hdr[i].cluster_type & CLUSTER_DRIVE) {
5628 cmd.Service = CACHESERVICE;
5629 cmd.OpCode = GDT_CLUST_INFO;
5630 if (ha->cache_feat & GDT_64BIT)
5631 cmd.u.cache64.DeviceNo = i;
5632 else
5633 cmd.u.cache.DeviceNo = i;
5634#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5635 gdth_do_req(srp, &cmd, cmnd, 30);
5636 if (srp->sr_command->SCp.Status == S_OK)
5637 rsc.hdr_list[i].cluster_type = srp->sr_command->SCp.Message;
5638#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5639 gdth_do_cmd(scp, &cmd, cmnd, 30);
5640 if (scp->SCp.Status == S_OK)
5641 rsc.hdr_list[i].cluster_type = scp->SCp.Message;
5642#else
5643 gdth_do_cmd(&scp, &cmd, cmnd, 30);
5644 if (scp.SCp.Status == S_OK)
5645 rsc.hdr_list[i].cluster_type = scp.SCp.Message;
5646#endif
5647 }
5648 }
5649#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5650 scsi_release_request(srp);
5651#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5652 scsi_release_command(scp);
5653#endif
5654
5655 if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan)))
5656 return -EFAULT;
5657 return 0;
5658}
5659
5660static int ioc_rescan(unsigned long arg, char *cmnd)
5661{
5662 gdth_ioctl_rescan rsc;
5663 gdth_cmd_str cmd;
5664 ushort i, status, hdr_cnt;
5665 ulong32 info;
5666 int hanum, cyls, hds, secs;
5667 ulong flags;
5668 gdth_ha_str *ha;
5669#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5670 Scsi_Request *srp;
5671#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5672 Scsi_Cmnd *scp;
5673#else
5674 Scsi_Cmnd scp;
5675#endif
5676
5677 if (copy_from_user(&rsc, (char *)arg, sizeof(gdth_ioctl_rescan)) ||
5678 rsc.ionode >= gdth_ctr_count)
5679 return -EFAULT;
5680 hanum = rsc.ionode;
5681 ha = HADATA(gdth_ctr_tab[hanum]);
5682 memset(&cmd, 0, sizeof(gdth_cmd_str));
5683
5684#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5685 srp = scsi_allocate_request(ha->sdev, GFP_KERNEL);
5686 if (!srp)
5687 return -ENOMEM;
5688 srp->sr_cmd_len = 12;
5689 srp->sr_use_sg = 0;
5690#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5691 scp = scsi_allocate_device(ha->sdev, 1, FALSE);
5692 if (!scp)
5693 return -ENOMEM;
5694 scp->cmd_len = 12;
5695 scp->use_sg = 0;
5696#else
5697 memset(&ha->sdev,0,sizeof(Scsi_Device));
5698 memset(&scp, 0,sizeof(Scsi_Cmnd));
5699 ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
5700 ha->sdev.id = scp.target = ha->sdev.host->this_id;
5701 scp.device = &ha->sdev;
5702#endif
5703
5704 if (rsc.flag == 0) {
5705
5706 cmd.Service = CACHESERVICE;
5707 if (ha->cache_feat & GDT_64BIT) {
5708 cmd.OpCode = GDT_X_INIT_HOST;
5709 cmd.u.cache64.DeviceNo = LINUX_OS;
5710 } else {
5711 cmd.OpCode = GDT_INIT;
5712 cmd.u.cache.DeviceNo = LINUX_OS;
5713 }
5714#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5715 gdth_do_req(srp, &cmd, cmnd, 30);
5716 status = (ushort)srp->sr_command->SCp.Status;
5717 info = (ulong32)srp->sr_command->SCp.Message;
5718#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5719 gdth_do_cmd(scp, &cmd, cmnd, 30);
5720 status = (ushort)scp->SCp.Status;
5721 info = (ulong32)scp->SCp.Message;
5722#else
5723 gdth_do_cmd(&scp, &cmd, cmnd, 30);
5724 status = (ushort)scp.SCp.Status;
5725 info = (ulong32)scp.SCp.Message;
5726#endif
5727 i = 0;
5728 hdr_cnt = (status == S_OK ? (ushort)info : 0);
5729 } else {
5730 i = rsc.hdr_no;
5731 hdr_cnt = i + 1;
5732 }
5733 for (; i < hdr_cnt && i < MAX_HDRIVES; ++i) {
5734 cmd.Service = CACHESERVICE;
5735 cmd.OpCode = GDT_INFO;
5736 if (ha->cache_feat & GDT_64BIT)
5737 cmd.u.cache64.DeviceNo = i;
5738 else
5739 cmd.u.cache.DeviceNo = i;
5740#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5741 gdth_do_req(srp, &cmd, cmnd, 30);
5742 status = (ushort)srp->sr_command->SCp.Status;
5743 info = (ulong32)srp->sr_command->SCp.Message;
5744#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5745 gdth_do_cmd(scp, &cmd, cmnd, 30);
5746 status = (ushort)scp->SCp.Status;
5747 info = (ulong32)scp->SCp.Message;
5748#else
5749 gdth_do_cmd(&scp, &cmd, cmnd, 30);
5750 status = (ushort)scp.SCp.Status;
5751 info = (ulong32)scp.SCp.Message;
5752#endif
5753 GDTH_LOCK_HA(ha, flags);
5754 rsc.hdr_list[i].bus = ha->virt_bus;
5755 rsc.hdr_list[i].target = i;
5756 rsc.hdr_list[i].lun = 0;
5757 if (status != S_OK) {
5758 ha->hdr[i].present = FALSE;
5759 } else {
5760 ha->hdr[i].present = TRUE;
5761 ha->hdr[i].size = info;
5762
5763 ha->hdr[i].size &= ~SECS32;
5764 gdth_eval_mapping(ha->hdr[i].size,&cyls,&hds,&secs);
5765 ha->hdr[i].heads = hds;
5766 ha->hdr[i].secs = secs;
5767
5768 ha->hdr[i].size = cyls * hds * secs;
5769 }
5770 GDTH_UNLOCK_HA(ha, flags);
5771 if (status != S_OK)
5772 continue;
5773
5774
5775
5776
5777
5778 cmd.Service = CACHESERVICE;
5779 cmd.OpCode = GDT_DEVTYPE;
5780 if (ha->cache_feat & GDT_64BIT)
5781 cmd.u.cache64.DeviceNo = i;
5782 else
5783 cmd.u.cache.DeviceNo = i;
5784#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5785 gdth_do_req(srp, &cmd, cmnd, 30);
5786 status = (ushort)srp->sr_command->SCp.Status;
5787 info = (ulong32)srp->sr_command->SCp.Message;
5788#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5789 gdth_do_cmd(scp, &cmd, cmnd, 30);
5790 status = (ushort)scp->SCp.Status;
5791 info = (ulong32)scp->SCp.Message;
5792#else
5793 gdth_do_cmd(&scp, &cmd, cmnd, 30);
5794 status = (ushort)scp.SCp.Status;
5795 info = (ulong32)scp.SCp.Message;
5796#endif
5797 GDTH_LOCK_HA(ha, flags);
5798 ha->hdr[i].devtype = (status == S_OK ? (ushort)info : 0);
5799 GDTH_UNLOCK_HA(ha, flags);
5800
5801 cmd.Service = CACHESERVICE;
5802 cmd.OpCode = GDT_CLUST_INFO;
5803 if (ha->cache_feat & GDT_64BIT)
5804 cmd.u.cache64.DeviceNo = i;
5805 else
5806 cmd.u.cache.DeviceNo = i;
5807#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5808 gdth_do_req(srp, &cmd, cmnd, 30);
5809 status = (ushort)srp->sr_command->SCp.Status;
5810 info = (ulong32)srp->sr_command->SCp.Message;
5811#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5812 gdth_do_cmd(scp, &cmd, cmnd, 30);
5813 status = (ushort)scp->SCp.Status;
5814 info = (ulong32)scp->SCp.Message;
5815#else
5816 gdth_do_cmd(&scp, &cmd, cmnd, 30);
5817 status = (ushort)scp.SCp.Status;
5818 info = (ulong32)scp.SCp.Message;
5819#endif
5820 GDTH_LOCK_HA(ha, flags);
5821 ha->hdr[i].cluster_type =
5822 ((status == S_OK && !shared_access) ? (ushort)info : 0);
5823 GDTH_UNLOCK_HA(ha, flags);
5824 rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
5825
5826 cmd.Service = CACHESERVICE;
5827 cmd.OpCode = GDT_RW_ATTRIBS;
5828 if (ha->cache_feat & GDT_64BIT)
5829 cmd.u.cache64.DeviceNo = i;
5830 else
5831 cmd.u.cache.DeviceNo = i;
5832#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5833 gdth_do_req(srp, &cmd, cmnd, 30);
5834 status = (ushort)srp->sr_command->SCp.Status;
5835 info = (ulong32)srp->sr_command->SCp.Message;
5836#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5837 gdth_do_cmd(scp, &cmd, cmnd, 30);
5838 status = (ushort)scp->SCp.Status;
5839 info = (ulong32)scp->SCp.Message;
5840#else
5841 gdth_do_cmd(&scp, &cmd, cmnd, 30);
5842 status = (ushort)scp.SCp.Status;
5843 info = (ulong32)scp.SCp.Message;
5844#endif
5845 GDTH_LOCK_HA(ha, flags);
5846 ha->hdr[i].rw_attribs = (status == S_OK ? (ushort)info : 0);
5847 GDTH_UNLOCK_HA(ha, flags);
5848 }
5849#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5850 scsi_release_request(srp);
5851#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5852 scsi_release_command(scp);
5853#endif
5854
5855 if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan)))
5856 return -EFAULT;
5857 return 0;
5858}
5859
5860static int gdth_ioctl(struct inode *inode, struct file *filep,
5861 unsigned int cmd, unsigned long arg)
5862{
5863 gdth_ha_str *ha;
5864#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5865 Scsi_Cmnd *scp;
5866#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5867 Scsi_Cmnd *scp;
5868#else
5869 Scsi_Cmnd scp;
5870#endif
5871 ulong flags;
5872 char cmnd[MAX_COMMAND_SIZE];
5873
5874 memset(cmnd, 0xff, 12);
5875
5876 TRACE(("gdth_ioctl() cmd 0x%x\n", cmd));
5877
5878 switch (cmd) {
5879 case GDTIOCTL_CTRCNT:
5880 {
5881 int cnt = gdth_ctr_count;
5882 if (put_user(cnt, (int *)arg))
5883 return -EFAULT;
5884 break;
5885 }
5886
5887 case GDTIOCTL_DRVERS:
5888 {
5889 int ver = (GDTH_VERSION<<8) | GDTH_SUBVERSION;
5890 if (put_user(ver, (int *)arg))
5891 return -EFAULT;
5892 break;
5893 }
5894
5895 case GDTIOCTL_OSVERS:
5896 {
5897 gdth_ioctl_osvers osv;
5898
5899 osv.version = (unchar)(LINUX_VERSION_CODE >> 16);
5900 osv.subversion = (unchar)(LINUX_VERSION_CODE >> 8);
5901 osv.revision = (ushort)(LINUX_VERSION_CODE & 0xff);
5902 if (copy_to_user((char *)arg, &osv, sizeof(gdth_ioctl_osvers)))
5903 return -EFAULT;
5904 break;
5905 }
5906
5907 case GDTIOCTL_CTRTYPE:
5908 {
5909 gdth_ioctl_ctrtype ctrt;
5910
5911 if (copy_from_user(&ctrt, (char *)arg, sizeof(gdth_ioctl_ctrtype)) ||
5912 ctrt.ionode >= gdth_ctr_count)
5913 return -EFAULT;
5914 ha = HADATA(gdth_ctr_tab[ctrt.ionode]);
5915 if (ha->type == GDT_ISA || ha->type == GDT_EISA) {
5916 ctrt.type = (unchar)((ha->stype>>20) - 0x10);
5917 } else {
5918 if (ha->type != GDT_PCIMPR) {
5919 ctrt.type = (unchar)((ha->stype<<4) + 6);
5920 } else {
5921 ctrt.type =
5922 (ha->oem_id == OEM_ID_INTEL ? 0xfd : 0xfe);
5923 if (ha->stype >= 0x300)
5924 ctrt.ext_type = 0x6000 | ha->subdevice_id;
5925 else
5926 ctrt.ext_type = 0x6000 | ha->stype;
5927 }
5928 ctrt.device_id = ha->stype;
5929 ctrt.sub_device_id = ha->subdevice_id;
5930 }
5931 ctrt.info = ha->brd_phys;
5932 ctrt.oem_id = ha->oem_id;
5933 if (copy_to_user((char *)arg, &ctrt, sizeof(gdth_ioctl_ctrtype)))
5934 return -EFAULT;
5935 break;
5936 }
5937
5938 case GDTIOCTL_GENERAL:
5939 return ioc_general(arg, cmnd);
5940
5941 case GDTIOCTL_EVENT:
5942 return ioc_event(arg);
5943
5944 case GDTIOCTL_LOCKDRV:
5945 return ioc_lockdrv(arg);
5946
5947 case GDTIOCTL_LOCKCHN:
5948 {
5949 gdth_ioctl_lockchn lchn;
5950 unchar i, j;
5951
5952 if (copy_from_user(&lchn, (char *)arg, sizeof(gdth_ioctl_lockchn)) ||
5953 lchn.ionode >= gdth_ctr_count)
5954 return -EFAULT;
5955 ha = HADATA(gdth_ctr_tab[lchn.ionode]);
5956
5957 i = lchn.channel;
5958 if (i < ha->bus_cnt) {
5959 if (lchn.lock) {
5960 GDTH_LOCK_HA(ha, flags);
5961 ha->raw[i].lock = 1;
5962 GDTH_UNLOCK_HA(ha, flags);
5963 for (j = 0; j < ha->tid_cnt; ++j) {
5964 gdth_wait_completion(lchn.ionode, i, j);
5965 gdth_stop_timeout(lchn.ionode, i, j);
5966 }
5967 } else {
5968 GDTH_LOCK_HA(ha, flags);
5969 ha->raw[i].lock = 0;
5970 GDTH_UNLOCK_HA(ha, flags);
5971 for (j = 0; j < ha->tid_cnt; ++j) {
5972 gdth_start_timeout(lchn.ionode, i, j);
5973 gdth_next(lchn.ionode);
5974 }
5975 }
5976 }
5977 break;
5978 }
5979
5980 case GDTIOCTL_RESCAN:
5981 return ioc_rescan(arg, cmnd);
5982
5983 case GDTIOCTL_HDRLIST:
5984 return ioc_hdrlist(arg, cmnd);
5985
5986 case GDTIOCTL_RESET_BUS:
5987 {
5988 gdth_ioctl_reset res;
5989 int hanum, rval;
5990
5991 if (copy_from_user(&res, (char *)arg, sizeof(gdth_ioctl_reset)) ||
5992 res.ionode >= gdth_ctr_count)
5993 return -EFAULT;
5994 hanum = res.ionode;
5995 ha = HADATA(gdth_ctr_tab[hanum]);
5996
5997
5998#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
5999 scp = scsi_get_command(ha->sdev, GFP_KERNEL);
6000 if (!scp)
6001 return -ENOMEM;
6002 scp->cmd_len = 12;
6003 scp->use_sg = 0;
6004 scp->device->channel = virt_ctr ? 0 : res.number;
6005 rval = gdth_eh_bus_reset(scp);
6006 res.status = (rval == SUCCESS ? S_OK : S_GENERR);
6007 scsi_put_command(scp);
6008#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
6009 scp = scsi_allocate_device(ha->sdev, 1, FALSE);
6010 if (!scp)
6011 return -ENOMEM;
6012 scp->cmd_len = 12;
6013 scp->use_sg = 0;
6014 scp->channel = virt_ctr ? 0 : res.number;
6015 rval = gdth_eh_bus_reset(scp);
6016 res.status = (rval == SUCCESS ? S_OK : S_GENERR);
6017 scsi_release_command(scp);
6018#else
6019 memset(&ha->sdev,0,sizeof(Scsi_Device));
6020 memset(&scp, 0,sizeof(Scsi_Cmnd));
6021 ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
6022 ha->sdev.id = scp.target = ha->sdev.host->this_id;
6023 scp.device = &ha->sdev;
6024 scp.channel = virt_ctr ? 0 : res.number;
6025 rval = gdth_eh_bus_reset(&scp);
6026 res.status = (rval == SUCCESS ? S_OK : S_GENERR);
6027#endif
6028 if (copy_to_user((char *)arg, &res, sizeof(gdth_ioctl_reset)))
6029 return -EFAULT;
6030 break;
6031 }
6032
6033 case GDTIOCTL_RESET_DRV:
6034 return ioc_resetdrv(arg, cmnd);
6035
6036 default:
6037 break;
6038 }
6039 return 0;
6040}
6041
6042
6043
6044static void gdth_flush(int hanum)
6045{
6046 int i;
6047 gdth_ha_str *ha;
6048 gdth_cmd_str gdtcmd;
6049#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
6050 Scsi_Request *srp;
6051 Scsi_Device *sdev;
6052#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
6053 Scsi_Cmnd *scp;
6054 Scsi_Device *sdev;
6055#else
6056 Scsi_Cmnd scp;
6057 Scsi_Device sdev;
6058#endif
6059 char cmnd[MAX_COMMAND_SIZE];
6060 memset(cmnd, 0xff, MAX_COMMAND_SIZE);
6061
6062 TRACE2(("gdth_flush() hanum %d\n",hanum));
6063 ha = HADATA(gdth_ctr_tab[hanum]);
6064
6065#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
6066 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
6067 srp = scsi_allocate_request(sdev, GFP_KERNEL);
6068 if (!srp)
6069 return;
6070 srp->sr_cmd_len = 12;
6071 srp->sr_use_sg = 0;
6072#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
6073 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
6074 scp = scsi_allocate_device(sdev, 1, FALSE);
6075 if (!scp)
6076 return;
6077 scp->cmd_len = 12;
6078 scp->use_sg = 0;
6079#else
6080 memset(&sdev,0,sizeof(Scsi_Device));
6081 memset(&scp, 0,sizeof(Scsi_Cmnd));
6082 sdev.host = scp.host = gdth_ctr_tab[hanum];
6083 sdev.id = scp.target = sdev.host->this_id;
6084 scp.device = &sdev;
6085#endif
6086
6087 for (i = 0; i < MAX_HDRIVES; ++i) {
6088 if (ha->hdr[i].present) {
6089 gdtcmd.BoardNode = LOCALBOARD;
6090 gdtcmd.Service = CACHESERVICE;
6091 gdtcmd.OpCode = GDT_FLUSH;
6092 if (ha->cache_feat & GDT_64BIT) {
6093 gdtcmd.u.cache64.DeviceNo = i;
6094 gdtcmd.u.cache64.BlockNo = 1;
6095 gdtcmd.u.cache64.sg_canz = 0;
6096 } else {
6097 gdtcmd.u.cache.DeviceNo = i;
6098 gdtcmd.u.cache.BlockNo = 1;
6099 gdtcmd.u.cache.sg_canz = 0;
6100 }
6101 TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i));
6102#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
6103 gdth_do_req(srp, &gdtcmd, cmnd, 30);
6104#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
6105 gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
6106#else
6107 gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
6108#endif
6109 }
6110 }
6111#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
6112 scsi_release_request(srp);
6113 scsi_free_host_dev(sdev);
6114#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
6115 scsi_release_command(scp);
6116 scsi_free_host_dev(sdev);
6117#endif
6118}
6119
6120
6121static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
6122{
6123 int hanum;
6124#ifndef __alpha__
6125 gdth_cmd_str gdtcmd;
6126#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
6127 Scsi_Request *srp;
6128 Scsi_Device *sdev;
6129#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
6130 Scsi_Cmnd *scp;
6131 Scsi_Device *sdev;
6132#else
6133 Scsi_Cmnd scp;
6134 Scsi_Device sdev;
6135#endif
6136 char cmnd[MAX_COMMAND_SIZE];
6137#endif
6138
6139 TRACE2(("gdth_halt() event %d\n",(int)event));
6140 if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
6141 return NOTIFY_DONE;
6142
6143 printk("GDT-HA: Flushing all host drives .. ");
6144 for (hanum = 0; hanum < gdth_ctr_count; ++hanum) {
6145 gdth_flush(hanum);
6146
6147#ifndef __alpha__
6148
6149 memset(cmnd, 0xff, MAX_COMMAND_SIZE);
6150 gdtcmd.BoardNode = LOCALBOARD;
6151 gdtcmd.Service = CACHESERVICE;
6152 gdtcmd.OpCode = GDT_RESET;
6153 TRACE2(("gdth_halt(): reset controller %d\n", hanum));
6154#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
6155 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
6156 srp = scsi_allocate_request(sdev, GFP_KERNEL);
6157 if (!srp) {
6158 unregister_reboot_notifier(&gdth_notifier);
6159 return NOTIFY_OK;
6160 }
6161 srp->sr_cmd_len = 12;
6162 srp->sr_use_sg = 0;
6163 gdth_do_req(srp, &gdtcmd, cmnd, 10);
6164 scsi_release_request(srp);
6165 scsi_free_host_dev(sdev);
6166#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
6167 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
6168 scp = scsi_allocate_device(sdev, 1, FALSE);
6169 if (!scp) {
6170 unregister_reboot_notifier(&gdth_notifier);
6171 return NOTIFY_OK;
6172 }
6173 scp->cmd_len = 12;
6174 scp->use_sg = 0;
6175 gdth_do_cmd(scp, &gdtcmd, cmnd, 10);
6176 scsi_release_command(scp);
6177 scsi_free_host_dev(sdev);
6178#else
6179 memset(&sdev,0,sizeof(Scsi_Device));
6180 memset(&scp, 0,sizeof(Scsi_Cmnd));
6181 sdev.host = scp.host = gdth_ctr_tab[hanum];
6182 sdev.id = scp.target = sdev.host->this_id;
6183 scp.device = &sdev;
6184 gdth_do_cmd(&scp, &gdtcmd, cmnd, 10);
6185#endif
6186#endif
6187 }
6188 printk("Done.\n");
6189
6190#ifdef GDTH_STATISTICS
6191 del_timer(&gdth_timer);
6192#endif
6193 unregister_reboot_notifier(&gdth_notifier);
6194 return NOTIFY_OK;
6195}
6196
6197
6198#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) && !defined(MODULE)
6199
6200GDTH_INITFUNC(void, gdth_setup(char *str,int *ints))
6201{
6202 TRACE2(("gdth_setup() str %s ints[0] %d\n",
6203 str ? str:"NULL", ints ? ints[0]:0));
6204 internal_setup(str, ints);
6205}
6206
6207#else
6208
6209#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
6210static Scsi_Host_Template driver_template = {
6211 .proc_name = "gdth",
6212 .proc_info = gdth_proc_info,
6213 .name = "GDT SCSI Disk Array Controller",
6214 .detect = gdth_detect,
6215 .release = gdth_release,
6216 .info = gdth_info,
6217 .queuecommand = gdth_queuecommand,
6218 .eh_abort_handler = gdth_eh_abort,
6219 .eh_device_reset_handler = gdth_eh_device_reset,
6220 .eh_bus_reset_handler = gdth_eh_bus_reset,
6221 .eh_host_reset_handler = gdth_eh_host_reset,
6222 .bios_param = gdth_bios_param,
6223 .can_queue = GDTH_MAXCMDS,
6224 .this_id = -1,
6225 .sg_tablesize = GDTH_MAXSG,
6226 .cmd_per_lun = GDTH_MAXC_P_L,
6227 .unchecked_isa_dma = 1,
6228 .use_clustering = ENABLE_CLUSTERING,
6229#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
6230 .use_new_eh_code = 1,
6231#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)
6232 .highmem_io = 1,
6233#endif
6234#endif
6235};
6236#else
6237static Scsi_Host_Template driver_template = GDTH;
6238#endif
6239
6240#include "scsi_module.c"
6241#ifndef MODULE
6242__setup("gdth=", option_setup);
6243#endif
6244
6245#endif
6246