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