1 /************************************************************************
3 * ICP vortex GmbH: GDT ISA/EISA/PCI Disk Array Controllers *
4 * Intel Corporation: Storage RAID Controllers *
7 * Copyright (C) 1995-03 ICP vortex GmbH, Achim Leubner *
8 * Copyright (C) 2002-03 Intel Corporation *
9 * Copyright (C) 2003 Adaptec Inc. *
10 * <achim_leubner@adaptec.com> *
13 * Boji Tony Kannanthanam <boji.t.kannanthanam@intel.com> *
14 * Johannes Dinner <johannes_dinner@adaptec.com> *
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. *
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. *
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. *
30 * Tested with Linux 1.2.13, ..., 2.2.20, ..., 2.4.22 *
33 * Revision 1.64 2003/09/17 08:30:26 achim
34 * EISA/ISA controller scan disabled
35 * Command line switch probe_eisa_isa added
37 * Revision 1.63 2003/07/12 14:01:00 Daniele Bellucci <bellucda@tiscali.it>
38 * Minor cleanups in gdth_ioctl.
40 * Revision 1.62 2003/02/27 15:01:59 achim
41 * Dynamic DMA mapping implemented
42 * New (character device) IOCTL interface added
43 * Other controller related changes made
45 * Revision 1.61 2002/11/08 13:09:52 boji
46 * Added support for XSCALE based RAID Controllers
47 * Fixed SCREENSERVICE initialization in SMP cases
48 * Added checks for gdth_polling before GDTH_HA_LOCK
50 * Revision 1.60 2002/02/05 09:35:22 achim
51 * MODULE_LICENSE only if kernel >= 2.4.11
53 * Revision 1.59 2002/01/30 09:46:33 achim
56 * Revision 1.58 2002/01/29 15:30:02 achim
57 * Set default value of shared_access to Y
58 * New status S_CACHE_RESERV for clustering added
60 * Revision 1.57 2001/08/21 11:16:35 achim
63 * Revision 1.56 2001/08/09 11:19:39 achim
64 * Scsi_Host_Template changes
66 * Revision 1.55 2001/08/09 10:11:28 achim
67 * Command HOST_UNFREEZE_IO before cache service init.
69 * Revision 1.54 2001/07/20 13:48:12 achim
70 * Expand: gdth_analyse_hdrive() removed
72 * Revision 1.53 2001/07/17 09:52:49 achim
73 * Small OEM related change
75 * Revision 1.52 2001/06/19 15:06:20 achim
76 * New host command GDT_UNFREEZE_IO added
78 * Revision 1.51 2001/05/22 06:42:37 achim
79 * PCI: Subdevice ID added
81 * Revision 1.50 2001/05/17 13:42:16 achim
82 * Support for Intel Storage RAID Controllers added
84 * Revision 1.50 2001/05/17 12:12:34 achim
85 * Support for Intel Storage RAID Controllers added
87 * Revision 1.49 2001/03/15 15:07:17 achim
88 * New __setup interface for boot command line options added
90 * Revision 1.48 2001/02/06 12:36:28 achim
91 * Bugfix Cluster protocol
93 * Revision 1.47 2001/01/10 14:42:06 achim
94 * New switch shared_access added
96 * Revision 1.46 2001/01/09 08:11:35 achim
97 * gdth_command() removed
98 * meaning of Scsi_Pointer members changed
100 * Revision 1.45 2000/11/16 12:02:24 achim
101 * Changes for kernel 2.4
103 * Revision 1.44 2000/10/11 08:44:10 achim
104 * Clustering changes: New flag media_changed added
106 * Revision 1.43 2000/09/20 12:59:01 achim
107 * DPMEM remap functions for all PCI controller types implemented
108 * Small changes for ia64 platform
110 * Revision 1.42 2000/07/20 09:04:50 achim
111 * Small changes for kernel 2.4
113 * Revision 1.41 2000/07/04 14:11:11 achim
114 * gdth_analyse_hdrive() added to rescan drives after online expansion
116 * Revision 1.40 2000/06/27 11:24:16 achim
117 * Changes Clustering, Screenservice
119 * Revision 1.39 2000/06/15 13:09:04 achim
120 * Changes for gdth_do_cmd()
122 * Revision 1.38 2000/06/15 12:08:43 achim
123 * Bugfix gdth_sync_event(), service SCREENSERVICE
124 * Data direction for command 0xc2 changed to DOU
126 * Revision 1.37 2000/05/25 13:50:10 achim
127 * New driver parameter virt_ctr added
129 * Revision 1.36 2000/05/04 08:50:46 achim
130 * Event buffer now in gdth_ha_str
132 * Revision 1.35 2000/03/03 10:44:08 achim
133 * New event_string only valid for the RP controller family
135 * Revision 1.34 2000/03/02 14:55:29 achim
136 * New mechanism for async. event handling implemented
138 * Revision 1.33 2000/02/21 15:37:37 achim
139 * Bugfix Alpha platform + DPMEM above 4GB
141 * Revision 1.32 2000/02/14 16:17:37 achim
142 * Bugfix sense_buffer[] + raw devices
144 * Revision 1.31 2000/02/10 10:29:00 achim
145 * Delete sense_buffer[0], if command OK
147 * Revision 1.30 1999/11/02 13:42:39 achim
148 * ARRAY_DRV_LIST2 implemented
149 * Now 255 log. and 100 host drives supported
151 * Revision 1.29 1999/10/05 13:28:47 achim
152 * GDT_CLUST_RESET added
154 * Revision 1.28 1999/08/12 13:44:54 achim
156 * Cluster drives -> removeable drives
158 * Revision 1.27 1999/06/22 07:22:38 achim
161 * Revision 1.26 1999/06/10 16:09:12 achim
162 * Cluster Host Drive support: Bugfixes
164 * Revision 1.25 1999/06/01 16:03:56 achim
165 * gdth_init_pci(): Manipulate config. space to start RP controller
167 * Revision 1.24 1999/05/26 11:53:06 achim
168 * Cluster Host Drive support added
170 * Revision 1.23 1999/03/26 09:12:31 achim
171 * Default value for hdr_channel set to 0
173 * Revision 1.22 1999/03/22 16:27:16 achim
174 * Bugfix: gdth_store_event() must not be locked with GDTH_LOCK_HA()
176 * Revision 1.21 1999/03/16 13:40:34 achim
177 * Problems with reserved drives solved
178 * gdth_eh_bus_reset() implemented
180 * Revision 1.20 1999/03/10 09:08:13 achim
181 * Bugfix: Corrections in gdth_direction_tab[] made
182 * Bugfix: Increase command timeout (gdth_update_timeout()) NOT in gdth_putq()
184 * Revision 1.19 1999/03/05 14:38:16 achim
185 * Bugfix: Heads/Sectors mapping for reserved devices possibly wrong
186 * -> gdth_eval_mapping() implemented, changes in gdth_bios_param()
187 * INIT_RETRIES set to 100s to avoid DEINIT-Timeout for controllers
188 * with BIOS disabled and memory test set to Intensive
189 * Enhanced /proc support
191 * Revision 1.18 1999/02/24 09:54:33 achim
192 * Command line parameter hdr_channel implemented
193 * Bugfix for EISA controllers + Linux 2.2.x
195 * Revision 1.17 1998/12/17 15:58:11 achim
196 * Command line parameters implemented
197 * Changes for Alpha platforms
198 * PCI controller scan changed
199 * SMP support improved (spin_lock_irqsave(),...)
200 * New async. events, new scan/reserve commands included
202 * Revision 1.16 1998/09/28 16:08:46 achim
203 * GDT_PCIMPR: DPMEM remapping, if required
206 * Revision 1.15 1998/06/03 14:54:06 achim
207 * gdth_delay(), gdth_flush() implemented
208 * Bugfix: gdth_release() changed
210 * Revision 1.14 1998/05/22 10:01:17 achim
211 * mj: pcibios_strerror() removed
212 * Improved SMP support (if version >= 2.1.95)
213 * gdth_halt(): halt_called flag added (if version < 2.1)
215 * Revision 1.13 1998/04/16 09:14:57 achim
216 * Reserve drives (for raw service) implemented
217 * New error handling code enabled
218 * Get controller name from board_info() IOCTL
219 * Final round of PCI device driver patches by Martin Mares
221 * Revision 1.12 1998/03/03 09:32:37 achim
222 * Fibre channel controller support added
224 * Revision 1.11 1998/01/27 16:19:14 achim
226 * add_timer()/del_timer() instead of GDTH_TIMER
227 * scsi_add_timer()/scsi_del_timer() instead of SCSI_TIMER
228 * New error handling included
230 * Revision 1.10 1997/10/31 12:29:57 achim
231 * Read heads/sectors from host drive
233 * Revision 1.9 1997/09/04 10:07:25 achim
234 * IO-mapping with virt_to_bus(), gdth_readb(), gdth_writeb(), ...
235 * register_reboot_notifier() to get a notify on shutown used
237 * Revision 1.8 1997/04/02 12:14:30 achim
238 * Version 1.00 (see gdth.h), tested with kernel 2.0.29
240 * Revision 1.7 1997/03/12 13:33:37 achim
241 * gdth_reset() changed, new async. events
243 * Revision 1.6 1997/03/04 14:01:11 achim
244 * Shutdown routine gdth_halt() implemented
246 * Revision 1.5 1997/02/21 09:08:36 achim
247 * New controller included (RP, RP1, RP2 series)
248 * IOCTL interface implemented
250 * Revision 1.4 1996/07/05 12:48:55 achim
251 * Function gdth_bios_param() implemented
252 * New constant GDTH_MAXC_P_L inserted
253 * GDT_WRITE_THR, GDT_EXT_INFO implemented
254 * Function gdth_reset() changed
256 * Revision 1.3 1996/05/10 09:04:41 achim
257 * Small changes for Linux 1.2.13
259 * Revision 1.2 1996/05/09 12:45:27 achim
260 * Loadable module support implemented
261 * /proc support corrections made
263 * Revision 1.1 1996/04/11 07:35:57 achim
266 ************************************************************************/
268 /* All GDT Disk Array Controllers are fully supported by this driver.
269 * This includes the PCI/EISA/ISA SCSI Disk Array Controllers and the
270 * PCI Fibre Channel Disk Array Controllers. See gdth.h for a complete
271 * list of all controller types.
273 * If you have one or more GDT3000/3020 EISA controllers with
274 * controller BIOS disabled, you have to set the IRQ values with the
275 * command line option "gdth=irq1,irq2,...", where the irq1,irq2,... are
276 * the IRQ values for the EISA controllers.
278 * After the optional list of IRQ values, other possible
279 * command line options are:
280 * disable:Y disable driver
281 * disable:N enable driver
282 * reserve_mode:0 reserve no drives for the raw service
283 * reserve_mode:1 reserve all not init., removable drives
284 * reserve_mode:2 reserve all not init. drives
285 * reserve_list:h,b,t,l,h,b,t,l,... reserve particular drive(s) with
286 * h- controller no., b- channel no.,
287 * t- target ID, l- LUN
288 * reverse_scan:Y reverse scan order for PCI controllers
289 * reverse_scan:N scan PCI controllers like BIOS
290 * max_ids:x x - target ID count per channel (1..MAXID)
291 * rescan:Y rescan all channels/IDs
292 * rescan:N use all devices found until now
293 * virt_ctr:Y map every channel to a virtual controller
294 * virt_ctr:N use multi channel support
295 * hdr_channel:x x - number of virtual bus for host drives
296 * shared_access:Y disable driver reserve/release protocol to
297 * access a shared resource from several nodes,
298 * appropiate controller firmware required
299 * shared_access:N enable driver reserve/release protocol
300 * probe_eisa_isa:Y scan for EISA/ISA controllers
301 * probe_eisa_isa:N do not scan for EISA/ISA controllers
303 * The default values are: "gdth=disable:N,reserve_mode:1,reverse_scan:N,
304 * max_ids:127,rescan:N,virt_ctr:N,hdr_channel:0,
305 * shared_access:Y,probe_eisa_isa:N".
306 * Here is another example: "gdth=reserve_list:0,1,2,0,0,1,3,0,rescan:Y".
308 * When loading the gdth driver as a module, the same options are available.
309 * You can set the IRQs with "IRQ=...". However, the syntax to specify the
310 * options changes slightly. You must replace all ',' between options
311 * with ' ' and all ':' with '=' and you must use
312 * '1' in place of 'Y' and '0' in place of 'N'.
314 * Default: "modprobe gdth disable=0 reserve_mode=1 reverse_scan=0
315 * max_ids=127 rescan=0 virt_ctr=0 hdr_channel=0 shared_access=0
317 * The other example: "modprobe gdth reserve_list=0,1,2,0,0,1,3,0 rescan=1".
320 /* The meaning of the Scsi_Pointer members in this driver is as follows:
322 * this_residual: Command priority
323 * buffer: phys. DMA sense buffer
324 * dma_handle: phys. DMA buffer (kernel >= 2.4.0)
325 * buffers_residual: Timeout value
326 * Status: Command status (gdth_do_cmd()), DMA mem. mappings
327 * Message: Additional info (gdth_do_cmd()), DMA direction
328 * have_data_in: Flag for gdth_wait_completion()
329 * sent_command: Opcode special command
330 * phase: Service/parameter/return code special command
333 /* default: activate /proc and character device IOCTL interface */
334 #define GDTH_IOCTL_PROC
335 #define GDTH_IOCTL_CHRDEV
337 #include <linux/module.h>
339 #include <linux/version.h>
340 #include <linux/kernel.h>
341 #include <linux/types.h>
342 #include <linux/pci.h>
343 #include <linux/string.h>
344 #include <linux/ctype.h>
345 #include <linux/ioport.h>
346 #include <linux/delay.h>
347 #include <linux/sched.h>
348 #include <linux/interrupt.h>
349 #include <linux/in.h>
350 #include <linux/proc_fs.h>
351 #include <linux/time.h>
352 #include <linux/timer.h>
354 #include <linux/mc146818rtc.h>
356 #if LINUX_VERSION_CODE >= 0x020100
357 #include <linux/reboot.h>
359 #include <linux/bios32.h>
363 #include <asm/system.h>
365 #include <asm/uaccess.h>
366 #if LINUX_VERSION_CODE >= 0x020322
367 #include <linux/spinlock.h>
368 #elif LINUX_VERSION_CODE >= 0x02015F
369 #include <asm/spinlock.h>
372 #include <linux/blkdev.h>
376 #if LINUX_VERSION_CODE < 0x020503
382 static void gdth_delay(int milliseconds);
383 static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs);
384 static irqreturn_t gdth_interrupt(int irq, void *dev_id, struct pt_regs *regs);
385 static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp);
386 static int gdth_async_event(int hanum);
387 static void gdth_log_event(gdth_evt_data *dvr, char *buffer);
389 static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority);
390 static void gdth_next(int hanum);
391 static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b);
392 static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp);
393 static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source,
394 ushort idx, gdth_evt_data *evt);
395 static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr);
396 static void gdth_readapp_event(gdth_ha_str *ha, unchar application,
398 static void gdth_clear_events(void);
400 static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
401 char *buffer,ushort count);
402 static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp);
403 static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive);
405 static int gdth_search_eisa(ushort eisa_adr);
406 static int gdth_search_isa(ulong32 bios_adr);
407 static int gdth_search_pci(gdth_pci_str *pcistr);
408 static void gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
409 ushort vendor, ushort dev);
410 static void gdth_sort_pci(gdth_pci_str *pcistr, int cnt);
411 static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha);
412 static int gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha);
413 static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha);
415 static void gdth_enable_int(int hanum);
416 static int gdth_get_status(unchar *pIStatus,int irq);
417 static int gdth_test_busy(int hanum);
418 static int gdth_get_cmd_index(int hanum);
419 static void gdth_release_event(int hanum);
420 static int gdth_wait(int hanum,int index,ulong32 time);
421 static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
422 ulong32 p2,ulong32 p3);
423 static int gdth_search_drives(int hanum);
424 static int gdth_analyse_hdrive(int hanum, ushort hdrive);
426 static void *gdth_mmap(ulong paddr, ulong size);
427 static void gdth_munmap(void *addr);
429 static const char *gdth_ctr_name(int hanum);
431 #ifdef GDTH_IOCTL_CHRDEV
432 static int gdth_open(struct inode *inode, struct file *filep);
433 static int gdth_close(struct inode *inode, struct file *filep);
434 static int gdth_ioctl(struct inode *inode, struct file *filep,
435 unsigned int cmd, unsigned long arg);
438 #if LINUX_VERSION_CODE >= 0x010300
439 static void gdth_flush(int hanum);
440 #if LINUX_VERSION_CODE >= 0x020100
441 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
443 static int halt_called = FALSE;
444 void gdth_halt(void);
449 static unchar DebugState = DEBUG_GDTH;
452 #define MAX_SERBUF 160
453 static void ser_init(void);
454 static void ser_puts(char *str);
455 static void ser_putc(char c);
456 static int ser_printk(const char *fmt, ...);
457 static char strbuf[MAX_SERBUF+1];
459 #define COM_BASE 0x2f8
461 #define COM_BASE 0x3f8
463 static void ser_init()
465 unsigned port=COM_BASE;
469 /* 19200 Baud, if 9600: outb(12,port) */
479 static void ser_puts(char *str)
484 for (ptr=str;*ptr;++ptr)
488 static void ser_putc(char c)
490 unsigned port=COM_BASE;
492 while ((inb(port+5) & 0x20)==0);
496 while ((inb(port+5) & 0x20)==0);
501 static int ser_printk(const char *fmt, ...)
507 i = vsprintf(strbuf,fmt,args);
513 #define TRACE(a) {if (DebugState==1) {ser_printk a;}}
514 #define TRACE2(a) {if (DebugState==1 || DebugState==2) {ser_printk a;}}
515 #define TRACE3(a) {if (DebugState!=0) {ser_printk a;}}
517 #else /* !__SERIAL__ */
518 #define TRACE(a) {if (DebugState==1) {printk a;}}
519 #define TRACE2(a) {if (DebugState==1 || DebugState==2) {printk a;}}
520 #define TRACE3(a) {if (DebugState!=0) {printk a;}}
529 #ifdef GDTH_STATISTICS
530 static ulong32 max_rq=0, max_index=0, max_sg=0;
531 static ulong32 act_ints=0, act_ios=0, act_stats=0, act_rq=0;
532 static struct timer_list gdth_timer;
535 #define PTR2USHORT(a) (ushort)(ulong)(a)
536 #define GDTOFFSOF(a,b) (size_t)&(((a*)0)->b)
537 #define INDEX_OK(i,t) ((i)<sizeof(t)/sizeof((t)[0]))
539 #define NUMDATA(a) ( (gdth_num_str *)((a)->hostdata))
540 #define HADATA(a) (&((gdth_ext_str *)((a)->hostdata))->haext)
541 #define CMDDATA(a) (&((gdth_ext_str *)((a)->hostdata))->cmdext)
543 #define BUS_L2P(a,b) ((b)>(a)->virt_bus ? (b-1):(b))
545 #if LINUX_VERSION_CODE < 0x010300
546 static void *gdth_mmap(ulong paddr, ulong size)
548 if (paddr >= high_memory)
551 return (void *)paddr;
553 static void gdth_munmap(void *addr)
556 inline ulong32 virt_to_phys(volatile void *addr)
558 return (ulong32)addr;
560 inline void *phys_to_virt(ulong32 addr)
564 #define virt_to_bus virt_to_phys
565 #define bus_to_virt phys_to_virt
566 #define gdth_readb(addr) (*(volatile unchar *)(addr))
567 #define gdth_readw(addr) (*(volatile ushort *)(addr))
568 #define gdth_readl(addr) (*(volatile ulong32 *)(addr))
569 #define gdth_writeb(b,addr) (*(volatile unchar *)(addr) = (b))
570 #define gdth_writew(b,addr) (*(volatile ushort *)(addr) = (b))
571 #define gdth_writel(b,addr) (*(volatile ulong32 *)(addr) = (b))
572 #define memset_io(a,b,c) memset((void *)(a),(b),(c))
573 #define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
574 #define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
576 #define PCI_SLOT(devfn) ((devfn >> 3) & 0x1f)
578 #elif LINUX_VERSION_CODE < 0x020100
579 static int remapped = FALSE;
580 static void *gdth_mmap(ulong paddr, ulong size)
582 if ( paddr >= high_memory) {
584 return vremap(paddr, size);
586 return (void *)paddr;
589 static void gdth_munmap(void *addr)
595 #define gdth_readb(addr) readb((ulong)(addr))
596 #define gdth_readw(addr) readw((ulong)(addr))
597 #define gdth_readl(addr) (ulong32)readl((ulong)(addr))
598 #define gdth_writeb(b,addr) writeb((b),(ulong)(addr))
599 #define gdth_writew(b,addr) writew((b),(ulong)(addr))
600 #define gdth_writel(b,addr) writel((ulong32)(b),(ulong)(addr))
603 static void *gdth_mmap(ulong paddr, ulong size)
605 return ioremap(paddr, size);
607 static void gdth_munmap(void *addr)
609 return iounmap(addr);
611 #define gdth_readb(addr) readb((ulong)(addr))
612 #define gdth_readw(addr) readw((ulong)(addr))
613 #define gdth_readl(addr) (ulong32)readl((ulong)(addr))
614 #define gdth_writeb(b,addr) writeb((b),(ulong)(addr))
615 #define gdth_writew(b,addr) writew((b),(ulong)(addr))
616 #define gdth_writel(b,addr) writel((ulong32)(b),(ulong)(addr))
620 static unchar gdth_drq_tab[4] = {5,6,7,7}; /* DRQ table */
621 static unchar gdth_irq_tab[6] = {0,10,11,12,14,0}; /* IRQ table */
622 static unchar gdth_polling; /* polling if TRUE */
623 static unchar gdth_from_wait = FALSE; /* gdth_wait() */
624 static int wait_index,wait_hanum; /* gdth_wait() */
625 static int gdth_ctr_count = 0; /* controller count */
626 static int gdth_ctr_vcount = 0; /* virt. ctr. count */
627 static int gdth_ctr_released = 0; /* gdth_release() */
628 static struct Scsi_Host *gdth_ctr_tab[MAXHA]; /* controller table */
629 static struct Scsi_Host *gdth_ctr_vtab[MAXHA*MAXBUS]; /* virt. ctr. table */
630 static unchar gdth_write_through = FALSE; /* write through */
631 static gdth_evt_str ebuffer[MAX_EVENTS]; /* event buffer */
634 #ifdef GDTH_IOCTL_CHRDEV
638 #define DIN 1 /* IN data direction */
639 #define DOU 2 /* OUT data direction */
640 #define DNO DIN /* no data transfer */
641 #define DUN DIN /* unknown data direction */
642 static unchar gdth_direction_tab[0x100] = {
643 DNO,DNO,DIN,DIN,DOU,DIN,DIN,DOU,DIN,DUN,DOU,DOU,DUN,DUN,DUN,DIN,
644 DNO,DIN,DIN,DOU,DIN,DOU,DNO,DNO,DOU,DNO,DIN,DNO,DIN,DOU,DNO,DUN,
645 DIN,DUN,DIN,DUN,DOU,DIN,DUN,DUN,DIN,DIN,DOU,DNO,DUN,DIN,DOU,DOU,
646 DOU,DOU,DOU,DNO,DIN,DNO,DNO,DIN,DOU,DOU,DOU,DOU,DIN,DOU,DIN,DOU,
647 DOU,DOU,DIN,DIN,DIN,DNO,DUN,DNO,DNO,DNO,DUN,DNO,DOU,DIN,DUN,DUN,
648 DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DIN,DUN,DUN,DUN,DUN,DUN,
649 DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
650 DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
651 DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
652 DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
653 DUN,DUN,DUN,DUN,DUN,DNO,DNO,DUN,DIN,DNO,DOU,DUN,DNO,DUN,DOU,DOU,
654 DOU,DOU,DOU,DNO,DUN,DIN,DOU,DIN,DIN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
655 DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
656 DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
657 DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,
658 DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN
661 /* __initfunc, __initdata macros */
662 #if LINUX_VERSION_CODE >= 0x020322
663 #define GDTH_INITFUNC(type, func) type __init func
664 #include <linux/init.h>
665 #elif LINUX_VERSION_CODE >= 0x020126
666 #define GDTH_INITFUNC(type, func) __initfunc(type func)
667 #include <linux/init.h>
669 #define GDTH_INITFUNC(type, func) type func
674 #if LINUX_VERSION_CODE >= 0x020503
675 #define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock)
676 #define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags)
677 #define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags)
679 #define GDTH_LOCK_SCSI_DONE(dev, flags) spin_lock_irqsave(dev->host_lock,flags)
680 #define GDTH_UNLOCK_SCSI_DONE(dev, flags) spin_unlock_irqrestore(dev->host_lock,flags)
681 #define GDTH_LOCK_SCSI_DOCMD(dev) spin_lock_irq(dev->host_lock)
682 #define GDTH_UNLOCK_SCSI_DOCMD(dev) spin_unlock_irq(dev->host_lock)
684 #elif LINUX_VERSION_CODE >= 0x02015F
685 #define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock)
686 #define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags)
687 #define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags)
689 #define GDTH_LOCK_SCSI_DONE(flags) spin_lock_irqsave(&io_request_lock,flags)
690 #define GDTH_UNLOCK_SCSI_DONE(flags) spin_unlock_irqrestore(&io_request_lock,flags)
691 #define GDTH_LOCK_SCSI_DOCMD() spin_lock_irq(&io_request_lock)
692 #define GDTH_UNLOCK_SCSI_DOCMD() spin_unlock_irq(&io_request_lock)
695 #define GDTH_INIT_LOCK_HA(ha) do {} while (0)
696 #define GDTH_LOCK_HA(ha,flags) do {save_flags(flags); cli();} while (0)
697 #define GDTH_UNLOCK_HA(ha,flags) do {restore_flags(flags);} while (0)
699 #define GDTH_LOCK_SCSI_DONE(flags) do {} while (0)
700 #define GDTH_UNLOCK_SCSI_DONE(flags) do {} while (0)
701 #define GDTH_LOCK_SCSI_DOCMD() do {} while (0)
702 #define GDTH_UNLOCK_SCSI_DOCMD() do {} while (0)
705 /* LILO and modprobe/insmod parameters */
706 /* IRQ list for GDT3000/3020 EISA controllers */
707 static int irq[MAXHA] __initdata =
708 {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
709 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
710 /* disable driver flag */
711 static int disable __initdata = 0;
713 static int reserve_mode = 1;
715 static int reserve_list[MAX_RES_ARGS] =
716 {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
717 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
718 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
719 /* scan order for PCI controllers */
720 static int reverse_scan = 0;
721 /* virtual channel for the host drives */
722 static int hdr_channel = 0;
723 /* max. IDs per channel */
724 static int max_ids = MAXID;
726 static int rescan = 0;
727 /* map channels to virtual controllers */
728 static int virt_ctr = 0;
730 static int shared_access = 1;
731 /* enable support for EISA and ISA controllers */
732 static int probe_eisa_isa = 0;
735 #if LINUX_VERSION_CODE >= 0x02011A
736 /* parameters for modprobe/insmod */
737 MODULE_PARM(irq, "i");
738 MODULE_PARM(disable, "i");
739 MODULE_PARM(reserve_mode, "i");
740 MODULE_PARM(reserve_list, "4-" __MODULE_STRING(MAX_RES_ARGS) "i");
741 MODULE_PARM(reverse_scan, "i");
742 MODULE_PARM(hdr_channel, "i");
743 MODULE_PARM(max_ids, "i");
744 MODULE_PARM(rescan, "i");
745 MODULE_PARM(virt_ctr, "i");
746 MODULE_PARM(shared_access, "i");
747 MODULE_PARM(probe_eisa_isa, "i");
748 MODULE_AUTHOR("Achim Leubner");
750 #if LINUX_VERSION_CODE >= 0x02040B
751 MODULE_LICENSE("GPL");
755 #ifdef GDTH_IOCTL_CHRDEV
756 /* ioctl interface */
757 static struct file_operations gdth_fops = {
760 .release = gdth_close,
765 #if LINUX_VERSION_CODE >= 0x010300
766 #include <linux/stat.h>
767 #if LINUX_VERSION_CODE < 0x020322
768 struct proc_dir_entry proc_scsi_gdth = {
769 PROC_SCSI_GDTH, 4, "gdth",
770 S_IFDIR | S_IRUGO | S_IXUGO, 2
773 #include "gdth_proc.h"
774 #include "gdth_proc.c"
777 #if LINUX_VERSION_CODE >= 0x020100
778 /* notifier block to get a notify on system shutdown/halt/reboot */
779 static struct notifier_block gdth_notifier = {
785 static void gdth_delay(int milliseconds)
787 if (milliseconds == 0) {
790 #if LINUX_VERSION_CODE >= 0x020168
791 mdelay(milliseconds);
794 for (i = 0; i < milliseconds; ++i)
800 static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs)
802 *cyls = size /HEADS/SECS;
803 if (*cyls <= MAXCYLS) {
806 } else { /* too high for 64*32 */
807 *cyls = size /MEDHEADS/MEDSECS;
808 if (*cyls <= MAXCYLS) {
811 } else { /* too high for 127*63 */
812 *cyls = size /BIGHEADS/BIGSECS;
819 /* controller search and initialization functions */
821 GDTH_INITFUNC(static int, gdth_search_eisa(ushort eisa_adr))
825 TRACE(("gdth_search_eisa() adr. %x\n",eisa_adr));
826 id = inl(eisa_adr+ID0REG);
827 if (id == GDT3A_ID || id == GDT3B_ID) { /* GDT3000A or GDT3000B */
828 if ((inb(eisa_adr+EISAREG) & 8) == 0)
829 return 0; /* not EISA configured */
832 if (id == GDT3_ID) /* GDT3000 */
839 GDTH_INITFUNC(static int, gdth_search_isa(ulong32 bios_adr))
844 TRACE(("gdth_search_isa() bios adr. %x\n",bios_adr));
845 if ((addr = gdth_mmap(bios_adr+BIOS_ID_OFFS, sizeof(ulong32))) != NULL) {
846 id = gdth_readl(addr);
848 if (id == GDT2_ID) /* GDT2000 */
855 GDTH_INITFUNC(static int, gdth_search_pci(gdth_pci_str *pcistr))
859 TRACE(("gdth_search_pci()\n"));
862 for (device = 0; device <= PCI_DEVICE_ID_VORTEX_GDT6555; ++device)
863 gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device);
864 for (device = PCI_DEVICE_ID_VORTEX_GDT6x17RP;
865 device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP; ++device)
866 gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device);
867 gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX,
868 PCI_DEVICE_ID_VORTEX_GDTNEWRX);
869 gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
870 PCI_DEVICE_ID_INTEL_SRC);
871 gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
872 PCI_DEVICE_ID_INTEL_SRC_XSCALE);
876 #if LINUX_VERSION_CODE >= 0x20363
877 /* Vortex only makes RAID controllers.
878 * We do not really want to specify all 550 ids here, so wildcard match.
880 static struct pci_device_id gdthtable[] = {
881 {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID},
882 {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID},
883 {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID},
886 MODULE_DEVICE_TABLE(pci,gdthtable);
889 GDTH_INITFUNC(static void, gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
890 ushort vendor, ushort device))
892 ulong base0, base1, base2;
893 #if LINUX_VERSION_CODE >= 0x2015C
894 struct pci_dev *pdev;
900 TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n",
901 *cnt, vendor, device));
903 #if LINUX_VERSION_CODE >= 0x20363
905 while ((pdev = pci_find_device(vendor, device, pdev))
907 if (pci_enable_device(pdev))
911 /* GDT PCI controller found, resources are already in pdev */
912 pcistr[*cnt].pdev = pdev;
913 pcistr[*cnt].vendor_id = vendor;
914 pcistr[*cnt].device_id = device;
915 pcistr[*cnt].subdevice_id = pdev->subsystem_device;
916 pcistr[*cnt].bus = pdev->bus->number;
917 pcistr[*cnt].device_fn = pdev->devfn;
918 pcistr[*cnt].irq = pdev->irq;
919 base0 = pci_resource_flags(pdev, 0);
920 base1 = pci_resource_flags(pdev, 1);
921 base2 = pci_resource_flags(pdev, 2);
922 if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */
923 device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */
924 if (!(base0 & IORESOURCE_MEM))
926 pcistr[*cnt].dpmem = pci_resource_start(pdev, 0);
927 } else { /* GDT6110, GDT6120, .. */
928 if (!(base0 & IORESOURCE_MEM) ||
929 !(base2 & IORESOURCE_MEM) ||
930 !(base1 & IORESOURCE_IO))
932 pcistr[*cnt].dpmem = pci_resource_start(pdev, 2);
933 pcistr[*cnt].io_mm = pci_resource_start(pdev, 0);
934 pcistr[*cnt].io = pci_resource_start(pdev, 1);
936 TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n",
937 pcistr[*cnt].bus, PCI_SLOT(pcistr[*cnt].device_fn),
938 pcistr[*cnt].irq, pcistr[*cnt].dpmem));
941 #elif LINUX_VERSION_CODE >= 0x2015C
943 while ((pdev = pci_find_device(vendor, device, pdev))
947 /* GDT PCI controller found, resources are already in pdev */
948 pcistr[*cnt].pdev = pdev;
949 pcistr[*cnt].vendor_id = vendor;
950 pcistr[*cnt].device_id = device;
951 pcistr[*cnt].bus = pdev->bus->number;
952 pcistr[*cnt].device_fn = pdev->devfn;
953 pcibios_read_config_word(pcistr[*cnt].bus, pcistr[*cnt].device_fn,
954 PCI_SUBSYSTEM_ID, &pcistr[*cnt].subdevice_id);
955 pcistr[*cnt].irq = pdev->irq;
956 base0 = pdev->base_address[0];
957 base1 = pdev->base_address[1];
958 base2 = pdev->base_address[2];
959 if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */
960 device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */
961 if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
962 PCI_BASE_ADDRESS_SPACE_MEMORY)
964 pcistr[*cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK;
965 } else { /* GDT6110, GDT6120, .. */
966 if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
967 PCI_BASE_ADDRESS_SPACE_MEMORY ||
968 (base2 & PCI_BASE_ADDRESS_SPACE) !=
969 PCI_BASE_ADDRESS_SPACE_MEMORY ||
970 (base1 & PCI_BASE_ADDRESS_SPACE) !=
971 PCI_BASE_ADDRESS_SPACE_IO)
973 pcistr[*cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK;
974 pcistr[*cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK;
975 pcistr[*cnt].io = base1 & PCI_BASE_ADDRESS_IO_MASK;
977 TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n",
978 pcistr[*cnt].bus, PCI_SLOT(pcistr[*cnt].device_fn),
979 pcistr[*cnt].irq, pcistr[*cnt].dpmem));
984 while (!pcibios_find_device(vendor, device, idx++,
985 &pcistr[*cnt].bus,&pcistr[*cnt].device_fn)) {
988 /* GDT PCI ctr. found, now read resources from config space */
989 #if LINUX_VERSION_CODE >= 0x010300
990 #define GDTH_BASEP (int *)
994 if ((error = pcibios_read_config_dword(pcistr[*cnt].bus,
995 pcistr[*cnt].device_fn,
997 GDTH_BASEP&base0)) ||
998 (error = pcibios_read_config_dword(pcistr[*cnt].bus,
999 pcistr[*cnt].device_fn,
1001 GDTH_BASEP&base1)) ||
1002 (error = pcibios_read_config_dword(pcistr[*cnt].bus,
1003 pcistr[*cnt].device_fn,
1005 GDTH_BASEP&base2)) ||
1006 (error = pcibios_read_config_word(pcistr[*cnt].bus,
1007 pcistr[*cnt].device_fn,
1009 &pcistr[*cnt].subdevice_id)) ||
1010 (error = pcibios_read_config_byte(pcistr[*cnt].bus,
1011 pcistr[*cnt].device_fn,
1013 &pcistr[*cnt].irq))) {
1014 printk("GDT-PCI: error %d reading configuration space", error);
1017 pcistr[*cnt].vendor_id = vendor;
1018 pcistr[*cnt].device_id = device;
1019 if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */
1020 device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */
1021 if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
1022 PCI_BASE_ADDRESS_SPACE_MEMORY)
1024 pcistr[*cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK;
1025 } else { /* GDT6110, GDT6120, .. */
1026 if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
1027 PCI_BASE_ADDRESS_SPACE_MEMORY ||
1028 (base2 & PCI_BASE_ADDRESS_SPACE) !=
1029 PCI_BASE_ADDRESS_SPACE_MEMORY ||
1030 (base1 & PCI_BASE_ADDRESS_SPACE) !=
1031 PCI_BASE_ADDRESS_SPACE_IO)
1033 pcistr[*cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK;
1034 pcistr[*cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK;
1035 pcistr[*cnt].io = base1 & PCI_BASE_ADDRESS_IO_MASK;
1037 TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n",
1038 pcistr[*cnt].bus, PCI_SLOT(pcistr[*cnt].device_fn),
1039 pcistr[*cnt].irq, pcistr[*cnt].dpmem));
1046 GDTH_INITFUNC(static void, gdth_sort_pci(gdth_pci_str *pcistr, int cnt))
1051 TRACE(("gdth_sort_pci() cnt %d\n",cnt));
1057 for (i = 0; i < cnt-1; ++i) {
1058 if (!reverse_scan) {
1059 if ((pcistr[i].bus > pcistr[i+1].bus) ||
1060 (pcistr[i].bus == pcistr[i+1].bus &&
1061 PCI_SLOT(pcistr[i].device_fn) >
1062 PCI_SLOT(pcistr[i+1].device_fn))) {
1064 pcistr[i] = pcistr[i+1];
1069 if ((pcistr[i].bus < pcistr[i+1].bus) ||
1070 (pcistr[i].bus == pcistr[i+1].bus &&
1071 PCI_SLOT(pcistr[i].device_fn) <
1072 PCI_SLOT(pcistr[i+1].device_fn))) {
1074 pcistr[i] = pcistr[i+1];
1084 GDTH_INITFUNC(static int, gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha))
1087 unchar prot_ver,eisacf,i,irq_found;
1089 TRACE(("gdth_init_eisa() adr. %x\n",eisa_adr));
1091 /* disable board interrupts, deinitialize services */
1092 outb(0xff,eisa_adr+EDOORREG);
1093 outb(0x00,eisa_adr+EDENABREG);
1094 outb(0x00,eisa_adr+EINTENABREG);
1096 outb(0xff,eisa_adr+LDOORREG);
1097 retries = INIT_RETRIES;
1099 while (inb(eisa_adr+EDOORREG) != 0xff) {
1100 if (--retries == 0) {
1101 printk("GDT-EISA: Initialization error (DEINIT failed)\n");
1105 TRACE2(("wait for DEINIT: retries=%d\n",retries));
1107 prot_ver = inb(eisa_adr+MAILBOXREG);
1108 outb(0xff,eisa_adr+EDOORREG);
1109 if (prot_ver != PROTOCOL_VERSION) {
1110 printk("GDT-EISA: Illegal protocol version\n");
1113 ha->bmic = eisa_adr;
1114 ha->brd_phys = (ulong32)eisa_adr >> 12;
1116 outl(0,eisa_adr+MAILBOXREG);
1117 outl(0,eisa_adr+MAILBOXREG+4);
1118 outl(0,eisa_adr+MAILBOXREG+8);
1119 outl(0,eisa_adr+MAILBOXREG+12);
1122 if ((id = inl(eisa_adr+ID0REG)) == GDT3_ID) {
1123 ha->oem_id = OEM_ID_ICP;
1124 ha->type = GDT_EISA;
1126 outl(1,eisa_adr+MAILBOXREG+8);
1127 outb(0xfe,eisa_adr+LDOORREG);
1128 retries = INIT_RETRIES;
1130 while (inb(eisa_adr+EDOORREG) != 0xfe) {
1131 if (--retries == 0) {
1132 printk("GDT-EISA: Initialization error (get IRQ failed)\n");
1137 ha->irq = inb(eisa_adr+MAILBOXREG);
1138 outb(0xff,eisa_adr+EDOORREG);
1139 TRACE2(("GDT3000/3020: IRQ=%d\n",ha->irq));
1140 /* check the result */
1142 TRACE2(("Unknown IRQ, use IRQ table from cmd line !\n"));
1143 for (i = 0, irq_found = FALSE;
1144 i < MAXHA && irq[i] != 0xff; ++i) {
1145 if (irq[i]==10 || irq[i]==11 || irq[i]==12 || irq[i]==14) {
1153 printk("GDT-EISA: Can not detect controller IRQ,\n");
1154 printk("Use IRQ setting from command line (IRQ = %d)\n",
1157 printk("GDT-EISA: Initialization error (unknown IRQ), Enable\n");
1158 printk("the controller BIOS or use command line parameters\n");
1163 eisacf = inb(eisa_adr+EISAREG) & 7;
1164 if (eisacf > 4) /* level triggered */
1166 ha->irq = gdth_irq_tab[eisacf];
1167 ha->oem_id = OEM_ID_ICP;
1168 ha->type = GDT_EISA;
1175 GDTH_INITFUNC(static int, gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha))
1177 register gdt2_dpram_str *dp2_ptr;
1179 unchar irq_drq,prot_ver;
1182 TRACE(("gdth_init_isa() bios adr. %x\n",bios_adr));
1184 ha->brd = gdth_mmap(bios_adr, sizeof(gdt2_dpram_str));
1185 if (ha->brd == NULL) {
1186 printk("GDT-ISA: Initialization error (DPMEM remap error)\n");
1189 dp2_ptr = (gdt2_dpram_str *)ha->brd;
1190 gdth_writeb(1, &dp2_ptr->io.memlock); /* switch off write protection */
1191 /* reset interface area */
1192 memset_io((char *)&dp2_ptr->u,0,sizeof(dp2_ptr->u));
1193 if (gdth_readl(&dp2_ptr->u) != 0) {
1194 printk("GDT-PCI: Initialization error (DPMEM write error)\n");
1195 gdth_munmap(ha->brd);
1199 /* disable board interrupts, read DRQ and IRQ */
1200 gdth_writeb(0xff, &dp2_ptr->io.irqdel);
1201 gdth_writeb(0x00, &dp2_ptr->io.irqen);
1202 gdth_writeb(0x00, &dp2_ptr->u.ic.S_Status);
1203 gdth_writeb(0x00, &dp2_ptr->u.ic.Cmd_Index);
1205 irq_drq = gdth_readb(&dp2_ptr->io.rq);
1206 for (i=0; i<3; ++i) {
1207 if ((irq_drq & 1)==0)
1211 ha->drq = gdth_drq_tab[i];
1213 irq_drq = gdth_readb(&dp2_ptr->io.rq) >> 3;
1214 for (i=1; i<5; ++i) {
1215 if ((irq_drq & 1)==0)
1219 ha->irq = gdth_irq_tab[i];
1221 /* deinitialize services */
1222 gdth_writel(bios_adr, &dp2_ptr->u.ic.S_Info[0]);
1223 gdth_writeb(0xff, &dp2_ptr->u.ic.S_Cmd_Indx);
1224 gdth_writeb(0, &dp2_ptr->io.event);
1225 retries = INIT_RETRIES;
1227 while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xff) {
1228 if (--retries == 0) {
1229 printk("GDT-ISA: Initialization error (DEINIT failed)\n");
1230 gdth_munmap(ha->brd);
1235 prot_ver = (unchar)gdth_readl(&dp2_ptr->u.ic.S_Info[0]);
1236 gdth_writeb(0, &dp2_ptr->u.ic.Status);
1237 gdth_writeb(0xff, &dp2_ptr->io.irqdel);
1238 if (prot_ver != PROTOCOL_VERSION) {
1239 printk("GDT-ISA: Illegal protocol version\n");
1240 gdth_munmap(ha->brd);
1244 ha->oem_id = OEM_ID_ICP;
1246 ha->ic_all_size = sizeof(dp2_ptr->u);
1248 ha->brd_phys = bios_adr >> 4;
1250 /* special request to controller BIOS */
1251 gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[0]);
1252 gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[1]);
1253 gdth_writel(0x01, &dp2_ptr->u.ic.S_Info[2]);
1254 gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[3]);
1255 gdth_writeb(0xfe, &dp2_ptr->u.ic.S_Cmd_Indx);
1256 gdth_writeb(0, &dp2_ptr->io.event);
1257 retries = INIT_RETRIES;
1259 while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xfe) {
1260 if (--retries == 0) {
1261 printk("GDT-ISA: Initialization error\n");
1262 gdth_munmap(ha->brd);
1267 gdth_writeb(0, &dp2_ptr->u.ic.Status);
1268 gdth_writeb(0xff, &dp2_ptr->io.irqdel);
1273 GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
1275 register gdt6_dpram_str *dp6_ptr;
1276 register gdt6c_dpram_str *dp6c_ptr;
1277 register gdt6m_dpram_str *dp6m_ptr;
1281 int i, found = FALSE;
1282 #if LINUX_VERSION_CODE < 0x2015C
1286 TRACE(("gdth_init_pci()\n"));
1288 if (pcistr->vendor_id == PCI_VENDOR_ID_INTEL)
1289 ha->oem_id = OEM_ID_INTEL;
1291 ha->oem_id = OEM_ID_ICP;
1292 ha->brd_phys = (pcistr->bus << 8) | (pcistr->device_fn & 0xf8);
1293 ha->stype = (ulong32)pcistr->device_id;
1294 ha->subdevice_id = pcistr->subdevice_id;
1295 ha->irq = pcistr->irq;
1296 #if LINUX_VERSION_CODE >= 0x20400
1297 ha->pdev = pcistr->pdev;
1300 if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000/B */
1301 TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
1302 ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6_dpram_str));
1303 if (ha->brd == NULL) {
1304 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1307 /* check and reset interface area */
1308 dp6_ptr = (gdt6_dpram_str *)ha->brd;
1309 gdth_writel(DPMEM_MAGIC, &dp6_ptr->u);
1310 if (gdth_readl(&dp6_ptr->u) != DPMEM_MAGIC) {
1311 printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n",
1314 for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
1315 gdth_munmap(ha->brd);
1316 ha->brd = gdth_mmap(i, sizeof(ushort));
1317 if (ha->brd == NULL) {
1318 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1321 if (gdth_readw(ha->brd) != 0xffff) {
1322 TRACE2(("init_pci_old() address 0x%x busy\n", i));
1325 gdth_munmap(ha->brd);
1326 #if LINUX_VERSION_CODE >= 0x2015C
1327 pci_write_config_dword(pcistr->pdev,
1328 PCI_BASE_ADDRESS_0, i);
1330 pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
1331 PCI_BASE_ADDRESS_0, i);
1333 ha->brd = gdth_mmap(i, sizeof(gdt6_dpram_str));
1334 if (ha->brd == NULL) {
1335 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1338 dp6_ptr = (gdt6_dpram_str *)ha->brd;
1339 gdth_writel(DPMEM_MAGIC, &dp6_ptr->u);
1340 if (gdth_readl(&dp6_ptr->u) == DPMEM_MAGIC) {
1341 printk("GDT-PCI: Use free address at 0x%x\n", i);
1347 printk("GDT-PCI: No free address found!\n");
1348 gdth_munmap(ha->brd);
1352 memset_io((char *)&dp6_ptr->u,0,sizeof(dp6_ptr->u));
1353 if (gdth_readl(&dp6_ptr->u) != 0) {
1354 printk("GDT-PCI: Initialization error (DPMEM write error)\n");
1355 gdth_munmap(ha->brd);
1359 /* disable board interrupts, deinit services */
1360 gdth_writeb(0xff, &dp6_ptr->io.irqdel);
1361 gdth_writeb(0x00, &dp6_ptr->io.irqen);
1362 gdth_writeb(0x00, &dp6_ptr->u.ic.S_Status);
1363 gdth_writeb(0x00, &dp6_ptr->u.ic.Cmd_Index);
1365 gdth_writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]);
1366 gdth_writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx);
1367 gdth_writeb(0, &dp6_ptr->io.event);
1368 retries = INIT_RETRIES;
1370 while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xff) {
1371 if (--retries == 0) {
1372 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
1373 gdth_munmap(ha->brd);
1378 prot_ver = (unchar)gdth_readl(&dp6_ptr->u.ic.S_Info[0]);
1379 gdth_writeb(0, &dp6_ptr->u.ic.S_Status);
1380 gdth_writeb(0xff, &dp6_ptr->io.irqdel);
1381 if (prot_ver != PROTOCOL_VERSION) {
1382 printk("GDT-PCI: Illegal protocol version\n");
1383 gdth_munmap(ha->brd);
1388 ha->ic_all_size = sizeof(dp6_ptr->u);
1390 /* special command to controller BIOS */
1391 gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[0]);
1392 gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[1]);
1393 gdth_writel(0x01, &dp6_ptr->u.ic.S_Info[2]);
1394 gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[3]);
1395 gdth_writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx);
1396 gdth_writeb(0, &dp6_ptr->io.event);
1397 retries = INIT_RETRIES;
1399 while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xfe) {
1400 if (--retries == 0) {
1401 printk("GDT-PCI: Initialization error\n");
1402 gdth_munmap(ha->brd);
1407 gdth_writeb(0, &dp6_ptr->u.ic.S_Status);
1408 gdth_writeb(0xff, &dp6_ptr->io.irqdel);
1410 } else if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6555) { /* GDT6110, ... */
1411 ha->plx = (gdt6c_plx_regs *)pcistr->io;
1412 TRACE2(("init_pci_new() dpmem %lx irq %d\n",
1413 pcistr->dpmem,ha->irq));
1414 ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6c_dpram_str));
1415 if (ha->brd == NULL) {
1416 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1417 gdth_munmap(ha->brd);
1420 /* check and reset interface area */
1421 dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
1422 gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u);
1423 if (gdth_readl(&dp6c_ptr->u) != DPMEM_MAGIC) {
1424 printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n",
1427 for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
1428 gdth_munmap(ha->brd);
1429 ha->brd = gdth_mmap(i, sizeof(ushort));
1430 if (ha->brd == NULL) {
1431 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1434 if (gdth_readw(ha->brd) != 0xffff) {
1435 TRACE2(("init_pci_plx() address 0x%x busy\n", i));
1438 gdth_munmap(ha->brd);
1439 #if LINUX_VERSION_CODE >= 0x2015C
1440 pci_write_config_dword(pcistr->pdev,
1441 PCI_BASE_ADDRESS_2, i);
1443 pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
1444 PCI_BASE_ADDRESS_2, i);
1446 ha->brd = gdth_mmap(i, sizeof(gdt6c_dpram_str));
1447 if (ha->brd == NULL) {
1448 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1451 dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
1452 gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u);
1453 if (gdth_readl(&dp6c_ptr->u) == DPMEM_MAGIC) {
1454 printk("GDT-PCI: Use free address at 0x%x\n", i);
1460 printk("GDT-PCI: No free address found!\n");
1461 gdth_munmap(ha->brd);
1465 memset_io((char *)&dp6c_ptr->u,0,sizeof(dp6c_ptr->u));
1466 if (gdth_readl(&dp6c_ptr->u) != 0) {
1467 printk("GDT-PCI: Initialization error (DPMEM write error)\n");
1468 gdth_munmap(ha->brd);
1472 /* disable board interrupts, deinit services */
1473 outb(0x00,PTR2USHORT(&ha->plx->control1));
1474 outb(0xff,PTR2USHORT(&ha->plx->edoor_reg));
1476 gdth_writeb(0x00, &dp6c_ptr->u.ic.S_Status);
1477 gdth_writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index);
1479 gdth_writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]);
1480 gdth_writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx);
1482 outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
1484 retries = INIT_RETRIES;
1486 while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xff) {
1487 if (--retries == 0) {
1488 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
1489 gdth_munmap(ha->brd);
1494 prot_ver = (unchar)gdth_readl(&dp6c_ptr->u.ic.S_Info[0]);
1495 gdth_writeb(0, &dp6c_ptr->u.ic.Status);
1496 if (prot_ver != PROTOCOL_VERSION) {
1497 printk("GDT-PCI: Illegal protocol version\n");
1498 gdth_munmap(ha->brd);
1502 ha->type = GDT_PCINEW;
1503 ha->ic_all_size = sizeof(dp6c_ptr->u);
1505 /* special command to controller BIOS */
1506 gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[0]);
1507 gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[1]);
1508 gdth_writel(0x01, &dp6c_ptr->u.ic.S_Info[2]);
1509 gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[3]);
1510 gdth_writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx);
1512 outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
1514 retries = INIT_RETRIES;
1516 while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) {
1517 if (--retries == 0) {
1518 printk("GDT-PCI: Initialization error\n");
1519 gdth_munmap(ha->brd);
1524 gdth_writeb(0, &dp6c_ptr->u.ic.S_Status);
1527 TRACE2(("init_pci_mpr() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
1528 ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6m_dpram_str));
1529 if (ha->brd == NULL) {
1530 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1534 /* manipulate config. space to enable DPMEM, start RP controller */
1535 #if LINUX_VERSION_CODE >= 0x20363
1536 pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command);
1538 pci_write_config_word(pcistr->pdev, PCI_COMMAND, command);
1539 if (pci_resource_start(pcistr->pdev, 8) == 1UL)
1540 pci_resource_start(pcistr->pdev, 8) = 0UL;
1542 pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, i);
1544 pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS,
1545 pci_resource_start(pcistr->pdev, 8));
1546 #elif LINUX_VERSION_CODE >= 0x2015C
1547 pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command);
1549 pci_write_config_word(pcistr->pdev, PCI_COMMAND, command);
1550 if (pcistr->pdev->rom_address == 1UL)
1551 pcistr->pdev->rom_address = 0UL;
1553 pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, i);
1555 pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS,
1556 pcistr->pdev->rom_address);
1558 pcibios_read_config_word(pcistr->bus, pcistr->device_fn,
1559 PCI_COMMAND, &command);
1561 pcibios_write_config_word(pcistr->bus, pcistr->device_fn,
1562 PCI_COMMAND, command);
1563 pcibios_read_config_dword(pcistr->bus, pcistr->device_fn,
1564 PCI_ROM_ADDRESS, &rom_addr);
1565 if (rom_addr == 1UL)
1568 pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
1569 PCI_ROM_ADDRESS, i);
1571 pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
1572 PCI_ROM_ADDRESS, rom_addr);
1575 /* Ensure that it is safe to access the non HW portions of DPMEM.
1576 * Aditional check needed for Xscale based RAID controllers */
1577 while( ((int)gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg) ) & 3 )
1580 /* check and reset interface area */
1581 dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
1582 gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u);
1583 if (gdth_readl(&dp6m_ptr->u) != DPMEM_MAGIC) {
1584 printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n",
1587 for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
1588 gdth_munmap(ha->brd);
1589 ha->brd = gdth_mmap(i, sizeof(ushort));
1590 if (ha->brd == NULL) {
1591 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1594 if (gdth_readw(ha->brd) != 0xffff) {
1595 TRACE2(("init_pci_mpr() address 0x%x busy\n", i));
1598 gdth_munmap(ha->brd);
1599 #if LINUX_VERSION_CODE >= 0x2015C
1600 pci_write_config_dword(pcistr->pdev,
1601 PCI_BASE_ADDRESS_0, i);
1603 pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
1604 PCI_BASE_ADDRESS_0, i);
1606 ha->brd = gdth_mmap(i, sizeof(gdt6m_dpram_str));
1607 if (ha->brd == NULL) {
1608 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1611 dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
1612 gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u);
1613 if (gdth_readl(&dp6m_ptr->u) == DPMEM_MAGIC) {
1614 printk("GDT-PCI: Use free address at 0x%x\n", i);
1620 printk("GDT-PCI: No free address found!\n");
1621 gdth_munmap(ha->brd);
1625 memset_io((char *)&dp6m_ptr->u,0,sizeof(dp6m_ptr->u));
1627 /* disable board interrupts, deinit services */
1628 gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) | 4,
1629 &dp6m_ptr->i960r.edoor_en_reg);
1630 gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
1631 gdth_writeb(0x00, &dp6m_ptr->u.ic.S_Status);
1632 gdth_writeb(0x00, &dp6m_ptr->u.ic.Cmd_Index);
1634 gdth_writel(pcistr->dpmem, &dp6m_ptr->u.ic.S_Info[0]);
1635 gdth_writeb(0xff, &dp6m_ptr->u.ic.S_Cmd_Indx);
1636 gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg);
1637 retries = INIT_RETRIES;
1639 while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xff) {
1640 if (--retries == 0) {
1641 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
1642 gdth_munmap(ha->brd);
1647 prot_ver = (unchar)gdth_readl(&dp6m_ptr->u.ic.S_Info[0]);
1648 gdth_writeb(0, &dp6m_ptr->u.ic.S_Status);
1649 if (prot_ver != PROTOCOL_VERSION) {
1650 printk("GDT-PCI: Illegal protocol version\n");
1651 gdth_munmap(ha->brd);
1655 ha->type = GDT_PCIMPR;
1656 ha->ic_all_size = sizeof(dp6m_ptr->u);
1658 /* special command to controller BIOS */
1659 gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[0]);
1660 gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[1]);
1661 gdth_writel(0x01, &dp6m_ptr->u.ic.S_Info[2]);
1662 gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[3]);
1663 gdth_writeb(0xfe, &dp6m_ptr->u.ic.S_Cmd_Indx);
1664 gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg);
1665 retries = INIT_RETRIES;
1667 while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) {
1668 if (--retries == 0) {
1669 printk("GDT-PCI: Initialization error\n");
1670 gdth_munmap(ha->brd);
1675 gdth_writeb(0, &dp6m_ptr->u.ic.S_Status);
1682 /* controller protocol functions */
1684 GDTH_INITFUNC(static void, gdth_enable_int(int hanum))
1688 gdt2_dpram_str *dp2_ptr;
1689 gdt6_dpram_str *dp6_ptr;
1690 gdt6m_dpram_str *dp6m_ptr;
1692 TRACE(("gdth_enable_int() hanum %d\n",hanum));
1693 ha = HADATA(gdth_ctr_tab[hanum]);
1694 GDTH_LOCK_HA(ha, flags);
1696 if (ha->type == GDT_EISA) {
1697 outb(0xff, ha->bmic + EDOORREG);
1698 outb(0xff, ha->bmic + EDENABREG);
1699 outb(0x01, ha->bmic + EINTENABREG);
1700 } else if (ha->type == GDT_ISA) {
1701 dp2_ptr = (gdt2_dpram_str *)ha->brd;
1702 gdth_writeb(1, &dp2_ptr->io.irqdel);
1703 gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);
1704 gdth_writeb(1, &dp2_ptr->io.irqen);
1705 } else if (ha->type == GDT_PCI) {
1706 dp6_ptr = (gdt6_dpram_str *)ha->brd;
1707 gdth_writeb(1, &dp6_ptr->io.irqdel);
1708 gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index);
1709 gdth_writeb(1, &dp6_ptr->io.irqen);
1710 } else if (ha->type == GDT_PCINEW) {
1711 outb(0xff, PTR2USHORT(&ha->plx->edoor_reg));
1712 outb(0x03, PTR2USHORT(&ha->plx->control1));
1713 } else if (ha->type == GDT_PCIMPR) {
1714 dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
1715 gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
1716 gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4,
1717 &dp6m_ptr->i960r.edoor_en_reg);
1719 GDTH_UNLOCK_HA(ha, flags);
1723 static int gdth_get_status(unchar *pIStatus,int irq)
1725 register gdth_ha_str *ha;
1728 TRACE(("gdth_get_status() irq %d ctr_count %d\n",
1729 irq,gdth_ctr_count));
1732 for (i=0; i<gdth_ctr_count; ++i) {
1733 ha = HADATA(gdth_ctr_tab[i]);
1734 if (ha->irq != (unchar)irq) /* check IRQ */
1736 if (ha->type == GDT_EISA)
1737 *pIStatus = inb((ushort)ha->bmic + EDOORREG);
1738 else if (ha->type == GDT_ISA)
1740 gdth_readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Cmd_Index);
1741 else if (ha->type == GDT_PCI)
1743 gdth_readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Cmd_Index);
1744 else if (ha->type == GDT_PCINEW)
1745 *pIStatus = inb(PTR2USHORT(&ha->plx->edoor_reg));
1746 else if (ha->type == GDT_PCIMPR)
1748 gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.edoor_reg);
1751 return i; /* board found */
1757 static int gdth_test_busy(int hanum)
1759 register gdth_ha_str *ha;
1760 register int gdtsema0 = 0;
1762 TRACE(("gdth_test_busy() hanum %d\n",hanum));
1764 ha = HADATA(gdth_ctr_tab[hanum]);
1765 if (ha->type == GDT_EISA)
1766 gdtsema0 = (int)inb(ha->bmic + SEMA0REG);
1767 else if (ha->type == GDT_ISA)
1768 gdtsema0 = (int)gdth_readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
1769 else if (ha->type == GDT_PCI)
1770 gdtsema0 = (int)gdth_readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
1771 else if (ha->type == GDT_PCINEW)
1772 gdtsema0 = (int)inb(PTR2USHORT(&ha->plx->sema0_reg));
1773 else if (ha->type == GDT_PCIMPR)
1775 (int)gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
1777 return (gdtsema0 & 1);
1781 static int gdth_get_cmd_index(int hanum)
1783 register gdth_ha_str *ha;
1786 TRACE(("gdth_get_cmd_index() hanum %d\n",hanum));
1788 ha = HADATA(gdth_ctr_tab[hanum]);
1789 for (i=0; i<GDTH_MAXCMDS; ++i) {
1790 if (ha->cmd_tab[i].cmnd == UNUSED_CMND) {
1791 ha->cmd_tab[i].cmnd = ha->pccb->RequestBuffer;
1792 ha->cmd_tab[i].service = ha->pccb->Service;
1793 ha->pccb->CommandIndex = (ulong32)i+2;
1801 static void gdth_set_sema0(int hanum)
1803 register gdth_ha_str *ha;
1805 TRACE(("gdth_set_sema0() hanum %d\n",hanum));
1807 ha = HADATA(gdth_ctr_tab[hanum]);
1808 if (ha->type == GDT_EISA) {
1809 outb(1, ha->bmic + SEMA0REG);
1810 } else if (ha->type == GDT_ISA) {
1811 gdth_writeb(1, &((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
1812 } else if (ha->type == GDT_PCI) {
1813 gdth_writeb(1, &((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
1814 } else if (ha->type == GDT_PCINEW) {
1815 outb(1, PTR2USHORT(&ha->plx->sema0_reg));
1816 } else if (ha->type == GDT_PCIMPR) {
1817 gdth_writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
1822 static void gdth_copy_command(int hanum)
1824 register gdth_ha_str *ha;
1825 register gdth_cmd_str *cmd_ptr;
1826 register gdt6m_dpram_str *dp6m_ptr;
1827 register gdt6c_dpram_str *dp6c_ptr;
1828 gdt6_dpram_str *dp6_ptr;
1829 gdt2_dpram_str *dp2_ptr;
1830 ushort cp_count,dp_offset,cmd_no;
1832 TRACE(("gdth_copy_command() hanum %d\n",hanum));
1834 ha = HADATA(gdth_ctr_tab[hanum]);
1835 cp_count = ha->cmd_len;
1836 dp_offset= ha->cmd_offs_dpmem;
1837 cmd_no = ha->cmd_cnt;
1841 if (ha->type == GDT_EISA)
1842 return; /* no DPMEM, no copy */
1844 /* set cpcount dword aligned */
1846 cp_count += (4 - (cp_count & 3));
1848 ha->cmd_offs_dpmem += cp_count;
1850 /* set offset and service, copy command to DPMEM */
1851 if (ha->type == GDT_ISA) {
1852 dp2_ptr = (gdt2_dpram_str *)ha->brd;
1853 gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET,
1854 &dp2_ptr->u.ic.comm_queue[cmd_no].offset);
1855 gdth_writew((ushort)cmd_ptr->Service,
1856 &dp2_ptr->u.ic.comm_queue[cmd_no].serv_id);
1857 memcpy_toio(&dp2_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
1858 } else if (ha->type == GDT_PCI) {
1859 dp6_ptr = (gdt6_dpram_str *)ha->brd;
1860 gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET,
1861 &dp6_ptr->u.ic.comm_queue[cmd_no].offset);
1862 gdth_writew((ushort)cmd_ptr->Service,
1863 &dp6_ptr->u.ic.comm_queue[cmd_no].serv_id);
1864 memcpy_toio(&dp6_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
1865 } else if (ha->type == GDT_PCINEW) {
1866 dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
1867 gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET,
1868 &dp6c_ptr->u.ic.comm_queue[cmd_no].offset);
1869 gdth_writew((ushort)cmd_ptr->Service,
1870 &dp6c_ptr->u.ic.comm_queue[cmd_no].serv_id);
1871 memcpy_toio(&dp6c_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
1872 } else if (ha->type == GDT_PCIMPR) {
1873 dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
1874 gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET,
1875 &dp6m_ptr->u.ic.comm_queue[cmd_no].offset);
1876 gdth_writew((ushort)cmd_ptr->Service,
1877 &dp6m_ptr->u.ic.comm_queue[cmd_no].serv_id);
1878 memcpy_toio(&dp6m_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
1883 static void gdth_release_event(int hanum)
1885 register gdth_ha_str *ha;
1887 TRACE(("gdth_release_event() hanum %d\n",hanum));
1888 ha = HADATA(gdth_ctr_tab[hanum]);
1890 #ifdef GDTH_STATISTICS
1893 for (i=0,j=0; j<GDTH_MAXCMDS; ++j) {
1894 if (ha->cmd_tab[j].cmnd != UNUSED_CMND)
1897 if (max_index < i) {
1899 TRACE3(("GDT: max_index = %d\n",(ushort)i));
1904 if (ha->pccb->OpCode == GDT_INIT)
1905 ha->pccb->Service |= 0x80;
1907 if (ha->type == GDT_EISA) {
1908 if (ha->pccb->OpCode == GDT_INIT) /* store DMA buffer */
1909 outl(ha->ccb_phys, ha->bmic + MAILBOXREG);
1910 outb(ha->pccb->Service, ha->bmic + LDOORREG);
1911 } else if (ha->type == GDT_ISA) {
1912 gdth_writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event);
1913 } else if (ha->type == GDT_PCI) {
1914 gdth_writeb(0, &((gdt6_dpram_str *)ha->brd)->io.event);
1915 } else if (ha->type == GDT_PCINEW) {
1916 outb(1, PTR2USHORT(&ha->plx->ldoor_reg));
1917 } else if (ha->type == GDT_PCIMPR) {
1918 gdth_writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.ldoor_reg);
1923 static int gdth_wait(int hanum,int index,ulong32 time)
1926 int answer_found = FALSE;
1928 TRACE(("gdth_wait() hanum %d index %d time %d\n",hanum,index,time));
1930 ha = HADATA(gdth_ctr_tab[hanum]);
1932 return 1; /* no wait required */
1934 gdth_from_wait = TRUE;
1936 gdth_interrupt((int)ha->irq,ha,NULL);
1937 if (wait_hanum==hanum && wait_index==index) {
1938 answer_found = TRUE;
1943 gdth_from_wait = FALSE;
1945 while (gdth_test_busy(hanum))
1948 return (answer_found);
1952 static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
1953 ulong32 p2,ulong32 p3)
1955 register gdth_ha_str *ha;
1956 register gdth_cmd_str *cmd_ptr;
1959 TRACE2(("gdth_internal_cmd() service %d opcode %d\n",service,opcode));
1961 ha = HADATA(gdth_ctr_tab[hanum]);
1963 memset((char*)cmd_ptr,0,sizeof(gdth_cmd_str));
1966 for (retries = INIT_RETRIES;;) {
1967 cmd_ptr->Service = service;
1968 cmd_ptr->RequestBuffer = INTERNAL_CMND;
1969 if (!(index=gdth_get_cmd_index(hanum))) {
1970 TRACE(("GDT: No free command index found\n"));
1973 gdth_set_sema0(hanum);
1974 cmd_ptr->OpCode = opcode;
1975 cmd_ptr->BoardNode = LOCALBOARD;
1976 if (service == CACHESERVICE) {
1977 if (opcode == GDT_IOCTL) {
1978 cmd_ptr->u.ioctl.subfunc = p1;
1979 cmd_ptr->u.ioctl.channel = p2;
1980 cmd_ptr->u.ioctl.param_size = (ushort)p3;
1981 cmd_ptr->u.ioctl.p_param = ha->scratch_phys;
1983 cmd_ptr->u.cache.DeviceNo = (ushort)p1;
1984 cmd_ptr->u.cache.BlockNo = p2;
1986 } else if (service == SCSIRAWSERVICE) {
1987 cmd_ptr->u.raw.direction = p1;
1988 cmd_ptr->u.raw.bus = (unchar)p2;
1989 cmd_ptr->u.raw.target = (unchar)p3;
1990 cmd_ptr->u.raw.lun = (unchar)(p3 >> 8);
1991 } else if (service == SCREENSERVICE) {
1992 if (opcode == GDT_REALTIME) {
1993 *(ulong32 *)&cmd_ptr->u.screen.su.data[0] = p1;
1994 *(ulong32 *)&cmd_ptr->u.screen.su.data[4] = p2;
1995 *(ulong32 *)&cmd_ptr->u.screen.su.data[8] = p3;
1998 ha->cmd_len = sizeof(gdth_cmd_str);
1999 ha->cmd_offs_dpmem = 0;
2001 gdth_copy_command(hanum);
2002 gdth_release_event(hanum);
2004 if (!gdth_wait(hanum,index,INIT_TIMEOUT)) {
2005 printk("GDT: Initialization error (timeout service %d)\n",service);
2008 if (ha->status != S_BSY || --retries == 0)
2013 return (ha->status != S_OK ? 0:1);
2017 /* search for devices */
2019 GDTH_INITFUNC(static int, gdth_search_drives(int hanum))
2021 register gdth_ha_str *ha;
2023 ulong32 bus_no, drv_cnt, drv_no, j;
2024 gdth_getch_str *chn;
2025 gdth_drlist_str *drl;
2026 gdth_iochan_str *ioc;
2027 gdth_raw_iochan_str *iocr;
2028 gdth_arcdl_str *alst;
2029 gdth_alist_str *alst2;
2030 gdth_oem_str_ioctl *oemstr;
2037 TRACE(("gdth_search_drives() hanum %d\n",hanum));
2038 ha = HADATA(gdth_ctr_tab[hanum]);
2040 /* initialize controller services, at first: screen service */
2041 if (!gdth_internal_cmd(hanum,SCREENSERVICE,GDT_INIT,0,0,0)) {
2042 printk("GDT: Initialization error screen service (code %d)\n",
2046 TRACE2(("gdth_search_drives(): SCREENSERVICE initialized\n"));
2049 /* read realtime clock info, send to controller */
2050 /* 1. wait for the falling edge of update flag */
2051 spin_lock_irqsave(&rtc_lock, flags);
2052 for (j = 0; j < 1000000; ++j)
2053 if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
2055 for (j = 0; j < 1000000; ++j)
2056 if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
2060 for (j = 0; j < 12; ++j)
2061 rtc[j] = CMOS_READ(j);
2062 } while (rtc[0] != CMOS_READ(0));
2063 spin_unlock_irqrestore(&rtc_lock, flags);
2064 TRACE2(("gdth_search_drives(): RTC: %x/%x/%x\n",*(ulong32 *)&rtc[0],
2065 *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8]));
2066 /* 3. send to controller firmware */
2067 gdth_internal_cmd(hanum,SCREENSERVICE,GDT_REALTIME, *(ulong32 *)&rtc[0],
2068 *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8]);
2071 /* unfreeze all IOs */
2072 gdth_internal_cmd(hanum,CACHESERVICE,GDT_UNFREEZE_IO,0,0,0);
2074 /* initialize cache service */
2075 if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0)) {
2076 printk("GDT: Initialization error cache service (code %d)\n",
2080 TRACE2(("gdth_search_drives(): CACHESERVICE initialized\n"));
2081 cdev_cnt = (ushort)ha->info;
2082 ha->fw_vers = ha->service;
2084 /* detect number of buses - try new IOCTL */
2085 iocr = (gdth_raw_iochan_str *)ha->pscratch;
2086 iocr->hdr.version = 0xffffffff;
2087 iocr->hdr.list_entries = MAXBUS;
2088 iocr->hdr.first_chan = 0;
2089 iocr->hdr.last_chan = MAXBUS-1;
2090 iocr->hdr.list_offset = GDTOFFSOF(gdth_raw_iochan_str, list[0]);
2091 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,IOCHAN_RAW_DESC,
2092 INVALID_CHANNEL,sizeof(gdth_raw_iochan_str))) {
2093 TRACE2(("IOCHAN_RAW_DESC supported!\n"));
2094 ha->bus_cnt = iocr->hdr.chan_count;
2095 for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
2096 if (iocr->list[bus_no].proc_id < MAXID)
2097 ha->bus_id[bus_no] = iocr->list[bus_no].proc_id;
2099 ha->bus_id[bus_no] = 0xff;
2103 chn = (gdth_getch_str *)ha->pscratch;
2104 for (bus_no = 0; bus_no < MAXBUS; ++bus_no) {
2105 chn->channel_no = bus_no;
2106 if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
2107 SCSI_CHAN_CNT | L_CTRL_PATTERN,
2108 IO_CHANNEL | INVALID_CHANNEL,
2109 sizeof(gdth_getch_str))) {
2111 printk("GDT: Error detecting channel count (0x%x)\n",
2117 if (chn->siop_id < MAXID)
2118 ha->bus_id[bus_no] = chn->siop_id;
2120 ha->bus_id[bus_no] = 0xff;
2122 ha->bus_cnt = (unchar)bus_no;
2124 TRACE2(("gdth_search_drives() %d channels\n",ha->bus_cnt));
2126 /* read cache configuration */
2127 if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_INFO,
2128 INVALID_CHANNEL,sizeof(gdth_cinfo_str))) {
2129 printk("GDT: Initialization error cache service (code %d)\n",
2133 ha->cpar = ((gdth_cinfo_str *)ha->pscratch)->cpar;
2134 TRACE2(("gdth_search_drives() cinfo: vs %x sta %d str %d dw %d b %d\n",
2135 ha->cpar.version,ha->cpar.state,ha->cpar.strategy,
2136 ha->cpar.write_back,ha->cpar.block_size));
2138 /* read board info and features */
2139 ha->more_proc = FALSE;
2140 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_INFO,
2141 INVALID_CHANNEL,sizeof(gdth_binfo_str))) {
2142 memcpy(&ha->binfo, (gdth_binfo_str *)ha->pscratch,
2143 sizeof(gdth_binfo_str));
2144 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_FEATURES,
2145 INVALID_CHANNEL,sizeof(gdth_bfeat_str))) {
2146 TRACE2(("BOARD_INFO/BOARD_FEATURES supported\n"));
2147 ha->bfeat = *(gdth_bfeat_str *)ha->pscratch;
2148 ha->more_proc = TRUE;
2151 TRACE2(("BOARD_INFO requires firmware >= 1.10/2.08\n"));
2152 strcpy(ha->binfo.type_string, gdth_ctr_name(hanum));
2154 TRACE2(("Controller name: %s\n",ha->binfo.type_string));
2156 /* read more informations */
2157 if (ha->more_proc) {
2158 /* physical drives, channel addresses */
2159 ioc = (gdth_iochan_str *)ha->pscratch;
2160 ioc->hdr.version = 0xffffffff;
2161 ioc->hdr.list_entries = MAXBUS;
2162 ioc->hdr.first_chan = 0;
2163 ioc->hdr.last_chan = MAXBUS-1;
2164 ioc->hdr.list_offset = GDTOFFSOF(gdth_iochan_str, list[0]);
2165 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,IOCHAN_DESC,
2166 INVALID_CHANNEL,sizeof(gdth_iochan_str))) {
2167 for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
2168 ha->raw[bus_no].address = ioc->list[bus_no].address;
2169 ha->raw[bus_no].local_no = ioc->list[bus_no].local_no;
2172 for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
2173 ha->raw[bus_no].address = IO_CHANNEL;
2174 ha->raw[bus_no].local_no = bus_no;
2177 for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
2178 chn = (gdth_getch_str *)ha->pscratch;
2179 chn->channel_no = ha->raw[bus_no].local_no;
2180 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
2181 SCSI_CHAN_CNT | L_CTRL_PATTERN,
2182 ha->raw[bus_no].address | INVALID_CHANNEL,
2183 sizeof(gdth_getch_str))) {
2184 ha->raw[bus_no].pdev_cnt = chn->drive_cnt;
2185 TRACE2(("Channel %d: %d phys. drives\n",
2186 bus_no,chn->drive_cnt));
2188 if (ha->raw[bus_no].pdev_cnt > 0) {
2189 drl = (gdth_drlist_str *)ha->pscratch;
2190 drl->sc_no = ha->raw[bus_no].local_no;
2191 drl->sc_cnt = ha->raw[bus_no].pdev_cnt;
2192 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
2193 SCSI_DR_LIST | L_CTRL_PATTERN,
2194 ha->raw[bus_no].address | INVALID_CHANNEL,
2195 sizeof(gdth_drlist_str))) {
2196 for (j = 0; j < ha->raw[bus_no].pdev_cnt; ++j)
2197 ha->raw[bus_no].id_list[j] = drl->sc_list[j];
2199 ha->raw[bus_no].pdev_cnt = 0;
2204 /* logical drives */
2205 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_DRV_CNT,
2206 INVALID_CHANNEL,sizeof(ulong32))) {
2207 drv_cnt = *(ulong32 *)ha->pscratch;
2208 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_DRV_LIST,
2209 INVALID_CHANNEL,drv_cnt * sizeof(ulong32))) {
2210 for (j = 0; j < drv_cnt; ++j) {
2211 drv_no = ((ulong32 *)ha->pscratch)[j];
2212 if (drv_no < MAX_LDRIVES) {
2213 ha->hdr[drv_no].is_logdrv = TRUE;
2214 TRACE2(("Drive %d is log. drive\n",drv_no));
2218 alst = (gdth_arcdl_str *)ha->pscratch;
2219 alst->entries_avail = MAX_LDRIVES;
2220 alst->first_entry = 0;
2221 alst->list_offset = GDTOFFSOF(gdth_arcdl_str, list[0]);
2222 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
2223 ARRAY_DRV_LIST2 | LA_CTRL_PATTERN,
2224 INVALID_CHANNEL, sizeof(gdth_arcdl_str) +
2225 (alst->entries_avail-1) * sizeof(gdth_alist_str))) {
2226 for (j = 0; j < alst->entries_init; ++j) {
2227 ha->hdr[j].is_arraydrv = alst->list[j].is_arrayd;
2228 ha->hdr[j].is_master = alst->list[j].is_master;
2229 ha->hdr[j].is_parity = alst->list[j].is_parity;
2230 ha->hdr[j].is_hotfix = alst->list[j].is_hotfix;
2231 ha->hdr[j].master_no = alst->list[j].cd_handle;
2233 } else if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
2234 ARRAY_DRV_LIST | LA_CTRL_PATTERN,
2235 0, 35 * sizeof(gdth_alist_str))) {
2236 for (j = 0; j < 35; ++j) {
2237 alst2 = &((gdth_alist_str *)ha->pscratch)[j];
2238 ha->hdr[j].is_arraydrv = alst2->is_arrayd;
2239 ha->hdr[j].is_master = alst2->is_master;
2240 ha->hdr[j].is_parity = alst2->is_parity;
2241 ha->hdr[j].is_hotfix = alst2->is_hotfix;
2242 ha->hdr[j].master_no = alst2->cd_handle;
2248 /* initialize raw service */
2249 if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0)) {
2250 printk("GDT: Initialization error raw service (code %d)\n",
2254 TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n"));
2256 /* set/get features raw service (scatter/gather) */
2257 if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_SET_FEAT,SCATTER_GATHER,
2259 TRACE2(("gdth_search_drives(): set features RAWSERVICE OK\n"));
2260 if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_GET_FEAT,0,0,0)) {
2261 TRACE2(("gdth_search_dr(): get feat RAWSERVICE %d\n",
2263 ha->raw_feat = (ushort)ha->info;
2267 /* set/get features cache service (equal to raw service) */
2268 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_SET_FEAT,0,
2269 SCATTER_GATHER,0)) {
2270 TRACE2(("gdth_search_drives(): set features CACHESERVICE OK\n"));
2271 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_GET_FEAT,0,0,0)) {
2272 TRACE2(("gdth_search_dr(): get feat CACHESERV. %d\n",
2274 ha->cache_feat = (ushort)ha->info;
2278 /* reserve drives for raw service */
2279 if (reserve_mode != 0) {
2280 gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE_ALL,
2281 reserve_mode == 1 ? 1 : 3, 0, 0);
2282 TRACE2(("gdth_search_drives(): RESERVE_ALL code %d\n",
2285 for (i = 0; i < MAX_RES_ARGS; i += 4) {
2286 if (reserve_list[i] == hanum && reserve_list[i+1] < ha->bus_cnt &&
2287 reserve_list[i+2] < ha->tid_cnt && reserve_list[i+3] < MAXLUN) {
2288 TRACE2(("gdth_search_drives(): reserve ha %d bus %d id %d lun %d\n",
2289 reserve_list[i], reserve_list[i+1],
2290 reserve_list[i+2], reserve_list[i+3]));
2291 if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE,0,
2292 reserve_list[i+1], reserve_list[i+2] |
2293 (reserve_list[i+3] << 8))) {
2294 printk("GDT: Error raw service (RESERVE, code %d)\n",
2300 /* Determine OEM string using IOCTL */
2301 oemstr = (gdth_oem_str_ioctl *)ha->pscratch;
2302 oemstr->params.ctl_version = 0x01;
2303 oemstr->params.buffer_size = sizeof(oemstr->text);
2304 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
2305 CACHE_READ_OEM_STRING_RECORD,INVALID_CHANNEL,
2306 sizeof(gdth_oem_str_ioctl))) {
2307 TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD OK\n"));
2308 printk("GDT CTR%d Vendor: %s\n",hanum,oemstr->text.oem_company_name);
2309 /* Save the Host Drive inquiry data */
2310 strlcpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id,
2311 sizeof(ha->oem_name));
2313 /* Old method, based on PCI ID */
2314 TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD failed\n"));
2315 if (ha->oem_id == OEM_ID_INTEL)
2316 strlcpy(ha->oem_name,"Intel ", sizeof(ha->oem_name));
2318 strlcpy(ha->oem_name,"ICP ", sizeof(ha->oem_name));
2321 /* scanning for host drives */
2322 for (i = 0; i < cdev_cnt; ++i)
2323 gdth_analyse_hdrive(hanum,i);
2325 TRACE(("gdth_search_drives() OK\n"));
2329 static int gdth_analyse_hdrive(int hanum,ushort hdrive)
2331 register gdth_ha_str *ha;
2332 int drv_cyls, drv_hds, drv_secs;
2334 TRACE(("gdth_analyse_hdrive() hanum %d drive %d\n",hanum,hdrive));
2335 if (hdrive >= MAX_HDRIVES)
2337 ha = HADATA(gdth_ctr_tab[hanum]);
2339 if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INFO,hdrive,0,0))
2341 ha->hdr[hdrive].present = TRUE;
2342 ha->hdr[hdrive].size = ha->info;
2344 /* evaluate mapping (sectors per head, heads per cylinder) */
2345 ha->hdr[hdrive].size &= ~SECS32;
2346 if (ha->info2 == 0) {
2347 gdth_eval_mapping(ha->hdr[hdrive].size,&drv_cyls,&drv_hds,&drv_secs);
2349 drv_hds = ha->info2 & 0xff;
2350 drv_secs = (ha->info2 >> 8) & 0xff;
2351 drv_cyls = ha->hdr[hdrive].size /drv_hds/drv_secs;
2353 ha->hdr[hdrive].heads = (unchar)drv_hds;
2354 ha->hdr[hdrive].secs = (unchar)drv_secs;
2356 ha->hdr[hdrive].size = drv_cyls * drv_hds * drv_secs;
2357 TRACE2(("gdth_search_dr() cdr. %d size %d hds %d scs %d\n",
2358 hdrive,ha->hdr[hdrive].size,drv_hds,drv_secs));
2360 /* get informations about device */
2361 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_DEVTYPE,hdrive,0,0)) {
2362 TRACE2(("gdth_search_dr() cache drive %d devtype %d\n",
2364 ha->hdr[hdrive].devtype = (ushort)ha->info;
2368 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_CLUST_INFO,hdrive,0,0)) {
2369 TRACE2(("gdth_search_dr() cache drive %d cluster info %d\n",
2372 ha->hdr[hdrive].cluster_type = (unchar)ha->info;
2375 /* R/W attributes */
2376 if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_RW_ATTRIBS,hdrive,0,0)) {
2377 TRACE2(("gdth_search_dr() cache drive %d r/w attrib. %d\n",
2379 ha->hdr[hdrive].rw_attribs = (unchar)ha->info;
2386 /* command queueing/sending functions */
2388 static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority)
2390 register gdth_ha_str *ha;
2391 register Scsi_Cmnd *pscp;
2392 register Scsi_Cmnd *nscp;
2396 TRACE(("gdth_putq() priority %d\n",priority));
2397 ha = HADATA(gdth_ctr_tab[hanum]);
2398 GDTH_LOCK_HA(ha, flags);
2400 scp->SCp.this_residual = (int)priority;
2401 #if LINUX_VERSION_CODE >= 0x02053C
2402 b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
2403 t = scp->device->id;
2405 b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
2408 #if LINUX_VERSION_CODE >= 0x010300
2409 if (priority >= DEFAULT_PRI) {
2410 if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
2411 (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) {
2412 TRACE2(("gdth_putq(): locked IO -> update_timeout()\n"));
2413 scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
2418 if (ha->req_first==NULL) {
2419 ha->req_first = scp; /* queue was empty */
2420 scp->SCp.ptr = NULL;
2421 } else { /* queue not empty */
2422 pscp = ha->req_first;
2423 nscp = (Scsi_Cmnd *)pscp->SCp.ptr;
2424 /* priority: 0-highest,..,0xff-lowest */
2425 while (nscp && (unchar)nscp->SCp.this_residual <= priority) {
2427 nscp = (Scsi_Cmnd *)pscp->SCp.ptr;
2429 pscp->SCp.ptr = (char *)scp;
2430 scp->SCp.ptr = (char *)nscp;
2432 GDTH_UNLOCK_HA(ha, flags);
2434 #ifdef GDTH_STATISTICS
2436 for (nscp=ha->req_first; nscp; nscp=(Scsi_Cmnd*)nscp->SCp.ptr)
2438 if (max_rq < flags) {
2440 TRACE3(("GDT: max_rq = %d\n",(ushort)max_rq));
2445 static void gdth_next(int hanum)
2447 register gdth_ha_str *ha;
2448 register Scsi_Cmnd *pscp;
2449 register Scsi_Cmnd *nscp;
2450 unchar b, t, l, firsttime;
2451 unchar this_cmd, next_cmd;
2455 TRACE(("gdth_next() hanum %d\n",hanum));
2456 ha = HADATA(gdth_ctr_tab[hanum]);
2458 GDTH_LOCK_HA(ha, flags);
2460 ha->cmd_cnt = ha->cmd_offs_dpmem = 0;
2461 this_cmd = firsttime = TRUE;
2462 next_cmd = gdth_polling ? FALSE:TRUE;
2465 for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) {
2466 if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr)
2467 pscp = (Scsi_Cmnd *)pscp->SCp.ptr;
2468 #if LINUX_VERSION_CODE >= 0x02053C
2469 b = virt_ctr ? NUMDATA(nscp->device->host)->busnum : nscp->device->channel;
2470 t = nscp->device->id;
2471 l = nscp->device->lun;
2473 b = virt_ctr ? NUMDATA(nscp->host)->busnum : nscp->channel;
2477 if (nscp->SCp.this_residual >= DEFAULT_PRI) {
2478 if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
2479 (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock))
2484 if (gdth_test_busy(hanum)) { /* controller busy ? */
2485 TRACE(("gdth_next() controller %d busy !\n",hanum));
2486 if (!gdth_polling) {
2487 GDTH_UNLOCK_HA(ha, flags);
2490 while (gdth_test_busy(hanum))
2496 #if LINUX_VERSION_CODE >= 0x010300
2497 if (nscp->done != gdth_scsi_done || nscp->cmnd[0] != 0xff)
2500 if (nscp->SCp.phase == -1) {
2501 nscp->SCp.phase = CACHESERVICE; /* default: cache svc. */
2502 if (nscp->cmnd[0] == TEST_UNIT_READY) {
2503 TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n",
2505 /* TEST_UNIT_READY -> set scan mode */
2506 if ((ha->scan_mode & 0x0f) == 0) {
2507 if (b == 0 && t == 0 && l == 0) {
2509 TRACE2(("Scan mode: 0x%x\n", ha->scan_mode));
2511 } else if ((ha->scan_mode & 0x0f) == 1) {
2512 if (b == 0 && ((t == 0 && l == 1) ||
2513 (t == 1 && l == 0))) {
2514 nscp->SCp.sent_command = GDT_SCAN_START;
2515 nscp->SCp.phase = ((ha->scan_mode & 0x10 ? 1:0) << 8)
2517 ha->scan_mode = 0x12;
2518 TRACE2(("Scan mode: 0x%x (SCAN_START)\n",
2521 ha->scan_mode &= 0x10;
2522 TRACE2(("Scan mode: 0x%x\n", ha->scan_mode));
2524 } else if (ha->scan_mode == 0x12) {
2525 if (b == ha->bus_cnt && t == ha->tid_cnt-1) {
2526 nscp->SCp.phase = SCSIRAWSERVICE;
2527 nscp->SCp.sent_command = GDT_SCAN_END;
2528 ha->scan_mode &= 0x10;
2529 TRACE2(("Scan mode: 0x%x (SCAN_END)\n",
2534 if (b == ha->virt_bus && nscp->cmnd[0] != INQUIRY &&
2535 nscp->cmnd[0] != READ_CAPACITY && nscp->cmnd[0] != MODE_SENSE &&
2536 (ha->hdr[t].cluster_type & CLUSTER_DRIVE)) {
2537 /* always GDT_CLUST_INFO! */
2538 nscp->SCp.sent_command = GDT_CLUST_INFO;
2543 if (nscp->SCp.sent_command != -1) {
2544 if ((nscp->SCp.phase & 0xff) == CACHESERVICE) {
2545 if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
2548 } else if ((nscp->SCp.phase & 0xff) == SCSIRAWSERVICE) {
2549 if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b))))
2553 memset((char*)nscp->sense_buffer,0,16);
2554 nscp->sense_buffer[0] = 0x70;
2555 nscp->sense_buffer[2] = NOT_READY;
2556 nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
2557 if (!nscp->SCp.have_data_in)
2558 nscp->SCp.have_data_in++;
2561 GDTH_UNLOCK_HA(ha,flags);
2562 /* io_request_lock already active ! */
2563 nscp->scsi_done(nscp);
2565 GDTH_LOCK_HA(ha,flags);
2570 #if LINUX_VERSION_CODE >= 0x010300
2571 if (nscp->done == gdth_scsi_done && nscp->cmnd[0] == 0xff) {
2572 if (!(cmd_index=gdth_special_cmd(hanum,nscp)))
2577 if (b != ha->virt_bus) {
2578 if (ha->raw[BUS_L2P(ha,b)].io_cnt[t] >= GDTH_MAX_RAW ||
2579 !(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b))))
2582 ha->raw[BUS_L2P(ha,b)].io_cnt[t]++;
2583 } else if (t >= MAX_HDRIVES || !ha->hdr[t].present || l != 0) {
2584 TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n",
2585 nscp->cmnd[0], b, t, l));
2586 nscp->result = DID_BAD_TARGET << 16;
2587 if (!nscp->SCp.have_data_in)
2588 nscp->SCp.have_data_in++;
2591 GDTH_UNLOCK_HA(ha,flags);
2592 /* io_request_lock already active ! */
2593 nscp->scsi_done(nscp);
2595 GDTH_LOCK_HA(ha,flags);
2598 switch (nscp->cmnd[0]) {
2599 case TEST_UNIT_READY:
2606 TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
2607 nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
2608 nscp->cmnd[4],nscp->cmnd[5]));
2609 if (ha->hdr[t].media_changed && nscp->cmnd[0] != INQUIRY) {
2610 /* return UNIT_ATTENTION */
2611 TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n",
2613 ha->hdr[t].media_changed = FALSE;
2614 memset((char*)nscp->sense_buffer,0,16);
2615 nscp->sense_buffer[0] = 0x70;
2616 nscp->sense_buffer[2] = UNIT_ATTENTION;
2617 nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
2618 if (!nscp->SCp.have_data_in)
2619 nscp->SCp.have_data_in++;
2622 GDTH_UNLOCK_HA(ha,flags);
2623 /* io_request_lock already active ! */
2624 nscp->scsi_done(nscp);
2626 GDTH_LOCK_HA(ha,flags);
2628 } else if (gdth_internal_cache_cmd(hanum,nscp)) {
2630 GDTH_UNLOCK_HA(ha,flags);
2631 /* io_request_lock already active ! */
2632 nscp->scsi_done(nscp);
2634 GDTH_LOCK_HA(ha,flags);
2638 case ALLOW_MEDIUM_REMOVAL:
2639 TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
2640 nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
2641 nscp->cmnd[4],nscp->cmnd[5]));
2642 if ( (nscp->cmnd[4]&1) && !(ha->hdr[t].devtype&1) ) {
2643 TRACE(("Prevent r. nonremov. drive->do nothing\n"));
2644 nscp->result = DID_OK << 16;
2645 nscp->sense_buffer[0] = 0;
2646 if (!nscp->SCp.have_data_in)
2647 nscp->SCp.have_data_in++;
2650 GDTH_UNLOCK_HA(ha,flags);
2651 /* io_request_lock already active ! */
2652 nscp->scsi_done(nscp);
2654 GDTH_LOCK_HA(ha,flags);
2657 nscp->cmnd[3] = (ha->hdr[t].devtype&1) ? 1:0;
2658 TRACE(("Prevent/allow r. %d rem. drive %d\n",
2659 nscp->cmnd[4],nscp->cmnd[3]));
2660 if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
2667 TRACE2(("cache cmd %s\n",nscp->cmnd[0] == RESERVE ?
2668 "RESERVE" : "RELEASE"));
2669 if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
2677 if (ha->hdr[t].media_changed) {
2678 /* return UNIT_ATTENTION */
2679 TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n",
2681 ha->hdr[t].media_changed = FALSE;
2682 memset((char*)nscp->sense_buffer,0,16);
2683 nscp->sense_buffer[0] = 0x70;
2684 nscp->sense_buffer[2] = UNIT_ATTENTION;
2685 nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
2686 if (!nscp->SCp.have_data_in)
2687 nscp->SCp.have_data_in++;
2690 GDTH_UNLOCK_HA(ha,flags);
2691 /* io_request_lock already active ! */
2692 nscp->scsi_done(nscp);
2694 GDTH_LOCK_HA(ha,flags);
2696 } else if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
2701 TRACE2(("cache cmd %x/%x/%x/%x/%x/%x unknown\n",nscp->cmnd[0],
2702 nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
2703 nscp->cmnd[4],nscp->cmnd[5]));
2704 printk("GDT: Unknown SCSI command 0x%x to cache service !\n",
2706 nscp->result = DID_ABORT << 16;
2707 if (!nscp->SCp.have_data_in)
2708 nscp->SCp.have_data_in++;
2711 GDTH_UNLOCK_HA(ha,flags);
2712 /* io_request_lock already active ! */
2713 nscp->scsi_done(nscp);
2715 GDTH_LOCK_HA(ha,flags);
2723 if (nscp == ha->req_first)
2724 ha->req_first = pscp = (Scsi_Cmnd *)nscp->SCp.ptr;
2726 pscp->SCp.ptr = nscp->SCp.ptr;
2731 if (ha->cmd_cnt > 0) {
2732 gdth_release_event(hanum);
2736 GDTH_UNLOCK_HA(ha, flags);
2738 if (gdth_polling && ha->cmd_cnt > 0) {
2739 if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT))
2740 printk("GDT: Controller %d: Command %d timed out !\n",
2745 static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
2746 char *buffer,ushort count)
2750 struct scatterlist *sl;
2755 cpcount = count<=(ushort)scp->bufflen ? count:(ushort)scp->bufflen;
2756 ha = HADATA(gdth_ctr_tab[hanum]);
2759 sl = (struct scatterlist *)scp->request_buffer;
2760 #if LINUX_VERSION_CODE >= 0x020400
2761 sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,PCI_DMA_FROMDEVICE);
2762 for (i=0,cpsum=0; i<sgcnt; ++i,++sl) {
2763 cpnow = (ushort)sg_dma_len(sl);
2764 TRACE(("copy_internal() now %d sum %d count %d %d\n",
2765 cpnow,cpsum,cpcount,(ushort)scp->bufflen));
2766 if (cpsum+cpnow > cpcount)
2767 cpnow = cpcount - cpsum;
2769 address = (char *)phys_to_virt(sg_dma_address(sl));
2770 memcpy(address,buffer,cpnow);
2771 if (cpsum == cpcount)
2775 pci_unmap_sg(ha->pdev,scp->request_buffer,
2776 scp->use_sg,PCI_DMA_FROMDEVICE);
2778 sgcnt = scp->use_sg;
2779 for (i=0,cpsum=0; i<sgcnt; ++i,++sl) {
2780 cpnow = (ushort)sl->length;
2781 TRACE(("copy_internal() now %d sum %d count %d %d\n",
2782 cpnow,cpsum,cpcount,(ushort)scp->bufflen));
2783 if (cpsum+cpnow > cpcount)
2784 cpnow = cpcount - cpsum;
2786 address = (char *)sl->address;
2787 memcpy(address,buffer,cpnow);
2788 if (cpsum == cpcount)
2794 TRACE(("copy_internal() count %d\n",cpcount));
2795 memcpy((char*)scp->request_buffer,buffer,cpcount);
2799 static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
2801 register gdth_ha_str *ha;
2804 gdth_rdcap_data rdc;
2806 gdth_modep_data mpd;
2808 ha = HADATA(gdth_ctr_tab[hanum]);
2809 #if LINUX_VERSION_CODE >= 0x02053C
2810 t = scp->device->id;
2814 TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n",
2817 switch (scp->cmnd[0]) {
2818 case TEST_UNIT_READY:
2821 TRACE2(("Test/Verify/Start hdrive %d\n",t));
2825 TRACE2(("Inquiry hdrive %d devtype %d\n",
2826 t,ha->hdr[t].devtype));
2827 inq.type_qual = (ha->hdr[t].devtype&4) ? TYPE_ROM:TYPE_DISK;
2828 /* you can here set all disks to removable, if you want to do
2829 a flush using the ALLOW_MEDIUM_REMOVAL command */
2830 inq.modif_rmb = 0x00;
2831 if ((ha->hdr[t].devtype & 1) ||
2832 (ha->hdr[t].cluster_type & CLUSTER_DRIVE))
2833 inq.modif_rmb = 0x80;
2837 strcpy(inq.vendor,ha->oem_name);
2838 sprintf(inq.product,"Host Drive #%02d",t);
2839 strcpy(inq.revision," ");
2840 gdth_copy_internal_data(hanum,scp,(char*)&inq,sizeof(gdth_inq_data));
2844 TRACE2(("Request sense hdrive %d\n",t));
2845 sd.errorcode = 0x70;
2850 gdth_copy_internal_data(hanum,scp,(char*)&sd,sizeof(gdth_sense_data));
2854 TRACE2(("Mode sense hdrive %d\n",t));
2855 memset((char*)&mpd,0,sizeof(gdth_modep_data));
2856 mpd.hd.data_length = sizeof(gdth_modep_data);
2857 mpd.hd.dev_par = (ha->hdr[t].devtype&2) ? 0x80:0;
2858 mpd.hd.bd_length = sizeof(mpd.bd);
2859 mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16;
2860 mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8;
2861 mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff);
2862 gdth_copy_internal_data(hanum,scp,(char*)&mpd,sizeof(gdth_modep_data));
2866 TRACE2(("Read capacity hdrive %d\n",t));
2867 rdc.last_block_no = ntohl(ha->hdr[t].size-1);
2868 rdc.block_length = ntohl(SECTOR_SIZE);
2869 gdth_copy_internal_data(hanum,scp,(char*)&rdc,sizeof(gdth_rdcap_data));
2873 TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0]));
2877 scp->result = DID_OK << 16;
2878 scp->sense_buffer[0] = 0;
2880 if (!scp->SCp.have_data_in)
2881 scp->SCp.have_data_in++;
2888 static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
2890 register gdth_ha_str *ha;
2891 register gdth_cmd_str *cmdp;
2892 struct scatterlist *sl;
2894 ulong32 no, phys_addr;
2895 int cmd_index, read_write, sgcnt;
2897 ha = HADATA(gdth_ctr_tab[hanum]);
2899 TRACE(("gdth_fill_cache_cmd() cmd 0x%x cmdsize %d hdrive %d\n",
2900 scp->cmnd[0],scp->cmd_len,hdrive));
2902 if (ha->type==GDT_EISA && ha->cmd_cnt>0)
2905 cmdp->Service = CACHESERVICE;
2906 cmdp->RequestBuffer = scp;
2907 /* search free command index */
2908 if (!(cmd_index=gdth_get_cmd_index(hanum))) {
2909 TRACE(("GDT: No free command index found\n"));
2912 /* if it's the first command, set command semaphore */
2913 if (ha->cmd_cnt == 0)
2914 gdth_set_sema0(hanum);
2918 if (scp->SCp.sent_command != -1)
2919 cmdp->OpCode = scp->SCp.sent_command; /* special cache cmd. */
2920 else if (scp->cmnd[0] == RESERVE)
2921 cmdp->OpCode = GDT_RESERVE_DRV;
2922 else if (scp->cmnd[0] == RELEASE)
2923 cmdp->OpCode = GDT_RELEASE_DRV;
2924 else if (scp->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
2925 if (scp->cmnd[4] & 1) /* prevent ? */
2926 cmdp->OpCode = GDT_MOUNT;
2927 else if (scp->cmnd[3] & 1) /* removable drive ? */
2928 cmdp->OpCode = GDT_UNMOUNT;
2930 cmdp->OpCode = GDT_FLUSH;
2931 } else if (scp->cmnd[0] == WRITE_6 || scp->cmnd[0] == WRITE_10 ||
2932 scp->cmnd[0] == WRITE_12) {
2934 if (gdth_write_through || ((ha->hdr[hdrive].rw_attribs & 1) &&
2935 (ha->cache_feat & GDT_WR_THROUGH)))
2936 cmdp->OpCode = GDT_WRITE_THR;
2938 cmdp->OpCode = GDT_WRITE;
2941 cmdp->OpCode = GDT_READ;
2944 cmdp->BoardNode = LOCALBOARD;
2945 cmdp->u.cache.DeviceNo = hdrive;
2946 cmdp->u.cache.BlockNo = 1;
2947 cmdp->u.cache.sg_canz = 0;
2950 if (scp->cmd_len != 6) {
2951 memcpy(&no, &scp->cmnd[2], sizeof(ulong32));
2952 cmdp->u.cache.BlockNo = ntohl(no);
2953 memcpy(&cnt, &scp->cmnd[7], sizeof(ushort));
2954 cmdp->u.cache.BlockCnt = (ulong32)ntohs(cnt);
2956 memcpy(&no, &scp->cmnd[0], sizeof(ulong32));
2957 cmdp->u.cache.BlockNo = ntohl(no) & 0x001fffffUL;
2958 cmdp->u.cache.BlockCnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4];
2962 cmdp->u.cache.DestAddr= 0xffffffff;
2963 sl = (struct scatterlist *)scp->request_buffer;
2964 sgcnt = scp->use_sg;
2965 #if LINUX_VERSION_CODE >= 0x020400
2966 scp->SCp.Status = GDTH_MAP_SG;
2967 scp->SCp.Message = (read_write == 1 ?
2968 PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
2969 sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message);
2970 for (i=0; i<sgcnt; ++i,++sl) {
2971 cmdp->u.cache.sg_lst[i].sg_ptr = sg_dma_address(sl);
2972 cmdp->u.cache.sg_lst[i].sg_len = sg_dma_len(sl);
2975 for (i=0; i<sgcnt; ++i,++sl) {
2976 cmdp->u.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
2977 cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length;
2980 cmdp->u.cache.sg_canz = (ulong32)i;
2982 #ifdef GDTH_STATISTICS
2983 if (max_sg < (ulong32)i) {
2984 max_sg = (ulong32)i;
2985 TRACE3(("GDT: max_sg = %d\n",i));
2989 cmdp->u.cache.sg_lst[i].sg_len = 0;
2991 #if LINUX_VERSION_CODE >= 0x020400
2992 scp->SCp.Status = GDTH_MAP_SINGLE;
2993 scp->SCp.Message = (read_write == 1 ?
2994 PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
2995 phys_addr = pci_map_single(ha->pdev,scp->request_buffer,
2996 scp->request_bufflen,scp->SCp.Message);
2997 scp->SCp.dma_handle = phys_addr;
2999 phys_addr = virt_to_bus(scp->request_buffer);
3001 if (ha->cache_feat & SCATTER_GATHER) {
3002 cmdp->u.cache.DestAddr = 0xffffffff;
3003 cmdp->u.cache.sg_canz = 1;
3004 cmdp->u.cache.sg_lst[0].sg_ptr = phys_addr;
3005 cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen;
3006 cmdp->u.cache.sg_lst[1].sg_len = 0;
3008 cmdp->u.cache.DestAddr = phys_addr;
3009 cmdp->u.cache.sg_canz= 0;
3013 TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
3014 cmdp->u.cache.DestAddr,cmdp->u.cache.sg_canz,
3015 cmdp->u.cache.sg_lst[0].sg_ptr,
3016 cmdp->u.cache.sg_lst[0].sg_len));
3017 TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n",
3018 cmdp->OpCode,cmdp->u.cache.BlockNo,cmdp->u.cache.BlockCnt));
3020 /* evaluate command size, check space */
3021 ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) +
3022 (ushort)cmdp->u.cache.sg_canz * sizeof(gdth_sg_str);
3023 if (ha->cmd_len & 3)
3024 ha->cmd_len += (4 - (ha->cmd_len & 3));
3026 if (ha->cmd_cnt > 0) {
3027 if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
3029 TRACE2(("gdth_fill_cache() DPMEM overflow\n"));
3030 ha->cmd_tab[cmd_index-2].cmnd = UNUSED_CMND;
3036 gdth_copy_command(hanum);
3040 static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
3042 register gdth_ha_str *ha;
3043 register gdth_cmd_str *cmdp;
3044 struct scatterlist *sl;
3046 ulong32 phys_addr, sense_paddr;
3047 int cmd_index, sgcnt;
3050 ha = HADATA(gdth_ctr_tab[hanum]);
3051 #if LINUX_VERSION_CODE >= 0x02053C
3052 t = scp->device->id;
3053 l = scp->device->lun;
3059 TRACE(("gdth_fill_raw_cmd() cmd 0x%x bus %d ID %d LUN %d\n",
3060 scp->cmnd[0],b,t,l));
3062 if (ha->type==GDT_EISA && ha->cmd_cnt>0)
3065 cmdp->Service = SCSIRAWSERVICE;
3066 cmdp->RequestBuffer = scp;
3067 /* search free command index */
3068 if (!(cmd_index=gdth_get_cmd_index(hanum))) {
3069 TRACE(("GDT: No free command index found\n"));
3072 /* if it's the first command, set command semaphore */
3073 if (ha->cmd_cnt == 0)
3074 gdth_set_sema0(hanum);
3077 if (scp->SCp.sent_command != -1) {
3078 cmdp->OpCode = scp->SCp.sent_command; /* special raw cmd. */
3079 cmdp->BoardNode = LOCALBOARD;
3080 cmdp->u.raw.direction = (scp->SCp.phase >> 8);
3081 TRACE2(("special raw cmd 0x%x param 0x%x\n",
3082 cmdp->OpCode, cmdp->u.raw.direction));
3084 /* evaluate command size */
3085 ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst);
3087 #if LINUX_VERSION_CODE >= 0x020400
3088 sense_paddr = pci_map_single(ha->pdev,scp->sense_buffer,
3089 16,PCI_DMA_FROMDEVICE);
3090 scp->SCp.buffer = (struct scatterlist *)sense_paddr;
3092 sense_paddr = virt_to_bus(scp->sense_buffer);
3094 cmdp->OpCode = GDT_WRITE; /* always */
3095 cmdp->BoardNode = LOCALBOARD;
3096 cmdp->u.raw.reserved = 0;
3097 cmdp->u.raw.mdisc_time = 0;
3098 cmdp->u.raw.mcon_time = 0;
3099 cmdp->u.raw.clen = scp->cmd_len;
3100 cmdp->u.raw.target = t;
3101 cmdp->u.raw.lun = l;
3102 cmdp->u.raw.bus = b;
3103 cmdp->u.raw.priority = 0;
3104 cmdp->u.raw.link_p = 0;
3105 cmdp->u.raw.sdlen = scp->request_bufflen;
3106 cmdp->u.raw.sense_len = 16;
3107 cmdp->u.raw.sense_data = sense_paddr;
3108 cmdp->u.raw.direction =
3109 gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN;
3110 memcpy(cmdp->u.raw.cmd,scp->cmnd,12);
3113 cmdp->u.raw.sdata = 0xffffffff;
3114 sl = (struct scatterlist *)scp->request_buffer;
3115 sgcnt = scp->use_sg;
3116 #if LINUX_VERSION_CODE >= 0x020400
3117 scp->SCp.Status = GDTH_MAP_SG;
3118 scp->SCp.Message = PCI_DMA_BIDIRECTIONAL;
3119 sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message);
3120 for (i=0; i<sgcnt; ++i,++sl) {
3121 cmdp->u.raw.sg_lst[i].sg_ptr = sg_dma_address(sl);
3122 cmdp->u.raw.sg_lst[i].sg_len = sg_dma_len(sl);
3125 for (i=0; i<sgcnt; ++i,++sl) {
3126 cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
3127 cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length;
3130 cmdp->u.raw.sg_ranz = (ulong32)i;
3132 #ifdef GDTH_STATISTICS
3133 if (max_sg < (ulong32)i) {
3134 max_sg = (ulong32)i;
3135 TRACE3(("GDT: max_sg = %d\n",i));
3139 cmdp->u.raw.sg_lst[i].sg_len = 0;
3141 #if LINUX_VERSION_CODE >= 0x020400
3142 scp->SCp.Status = GDTH_MAP_SINGLE;
3143 scp->SCp.Message = PCI_DMA_BIDIRECTIONAL;
3144 phys_addr = pci_map_single(ha->pdev,scp->request_buffer,
3145 scp->request_bufflen,scp->SCp.Message);
3146 scp->SCp.dma_handle = phys_addr;
3148 phys_addr = virt_to_bus(scp->request_buffer);
3150 if (ha->raw_feat & SCATTER_GATHER) {
3151 cmdp->u.raw.sdata = 0xffffffff;
3152 cmdp->u.raw.sg_ranz= 1;
3153 cmdp->u.raw.sg_lst[0].sg_ptr = phys_addr;
3154 cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen;
3155 cmdp->u.raw.sg_lst[1].sg_len = 0;
3157 cmdp->u.raw.sdata = phys_addr;
3158 cmdp->u.raw.sg_ranz= 0;
3161 TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
3162 cmdp->u.raw.sdata,cmdp->u.raw.sg_ranz,
3163 cmdp->u.raw.sg_lst[0].sg_ptr,
3164 cmdp->u.raw.sg_lst[0].sg_len));
3166 /* evaluate command size */
3167 ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) +
3168 (ushort)cmdp->u.raw.sg_ranz * sizeof(gdth_sg_str);
3171 if (ha->cmd_len & 3)
3172 ha->cmd_len += (4 - (ha->cmd_len & 3));
3174 if (ha->cmd_cnt > 0) {
3175 if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
3177 TRACE2(("gdth_fill_raw() DPMEM overflow\n"));
3178 ha->cmd_tab[cmd_index-2].cmnd = UNUSED_CMND;
3184 gdth_copy_command(hanum);
3188 static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp)
3190 register gdth_ha_str *ha;
3191 register gdth_cmd_str *cmdp;
3194 ha = HADATA(gdth_ctr_tab[hanum]);
3196 TRACE2(("gdth_special_cmd(): "));
3198 if (ha->type==GDT_EISA && ha->cmd_cnt>0)
3201 memcpy( cmdp, scp->request_buffer, sizeof(gdth_cmd_str));
3202 cmdp->RequestBuffer = scp;
3204 /* search free command index */
3205 if (!(cmd_index=gdth_get_cmd_index(hanum))) {
3206 TRACE(("GDT: No free command index found\n"));
3210 /* if it's the first command, set command semaphore */
3211 if (ha->cmd_cnt == 0)
3212 gdth_set_sema0(hanum);
3214 /* evaluate command size, check space */
3215 if (cmdp->OpCode == GDT_IOCTL) {
3216 TRACE2(("IOCTL\n"));
3218 GDTOFFSOF(gdth_cmd_str,u.ioctl.p_param) + sizeof(ulong32);
3219 } else if (cmdp->Service == CACHESERVICE) {
3220 TRACE2(("cache command %d\n",cmdp->OpCode));
3222 GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + sizeof(gdth_sg_str);
3223 } else if (cmdp->Service == SCSIRAWSERVICE) {
3224 TRACE2(("raw command %d/%d\n",cmdp->OpCode,cmdp->u.raw.cmd[0]));
3226 GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + sizeof(gdth_sg_str);
3229 if (ha->cmd_len & 3)
3230 ha->cmd_len += (4 - (ha->cmd_len & 3));
3232 if (ha->cmd_cnt > 0) {
3233 if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
3235 TRACE2(("gdth_special_cmd() DPMEM overflow\n"));
3236 ha->cmd_tab[cmd_index-2].cmnd = UNUSED_CMND;
3242 gdth_copy_command(hanum);
3247 /* Controller event handling functions */
3248 static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source,
3249 ushort idx, gdth_evt_data *evt)
3254 /* no GDTH_LOCK_HA() ! */
3255 TRACE2(("gdth_store_event() source %d idx %d\n", source, idx));
3256 if (source == 0) /* no source -> no event */
3259 if (ebuffer[elastidx].event_source == source &&
3260 ebuffer[elastidx].event_idx == idx &&
3261 ((evt->size != 0 && ebuffer[elastidx].event_data.size != 0 &&
3262 !memcmp((char *)&ebuffer[elastidx].event_data.eu,
3263 (char *)&evt->eu, evt->size)) ||
3264 (evt->size == 0 && ebuffer[elastidx].event_data.size == 0 &&
3265 !strcmp((char *)&ebuffer[elastidx].event_data.event_string,
3266 (char *)&evt->event_string)))) {
3267 e = &ebuffer[elastidx];
3268 do_gettimeofday(&tv);
3269 e->last_stamp = tv.tv_sec;
3272 if (ebuffer[elastidx].event_source != 0) { /* entry not free ? */
3274 if (elastidx == MAX_EVENTS)
3276 if (elastidx == eoldidx) { /* reached mark ? */
3278 if (eoldidx == MAX_EVENTS)
3282 e = &ebuffer[elastidx];
3283 e->event_source = source;
3285 do_gettimeofday(&tv);
3286 e->first_stamp = e->last_stamp = tv.tv_sec;
3288 e->event_data = *evt;
3294 static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr)
3300 TRACE2(("gdth_read_event() handle %d\n", handle));
3301 GDTH_LOCK_HA(ha, flags);
3306 estr->event_source = 0;
3308 if (eindex >= MAX_EVENTS) {
3309 GDTH_UNLOCK_HA(ha, flags);
3312 e = &ebuffer[eindex];
3313 if (e->event_source != 0) {
3314 if (eindex != elastidx) {
3315 if (++eindex == MAX_EVENTS)
3320 memcpy(estr, e, sizeof(gdth_evt_str));
3322 GDTH_UNLOCK_HA(ha, flags);
3326 static void gdth_readapp_event(gdth_ha_str *ha,
3327 unchar application, gdth_evt_str *estr)
3332 unchar found = FALSE;
3334 TRACE2(("gdth_readapp_event() app. %d\n", application));
3335 GDTH_LOCK_HA(ha, flags);
3338 e = &ebuffer[eindex];
3339 if (e->event_source == 0)
3341 if ((e->application & application) == 0) {
3342 e->application |= application;
3346 if (eindex == elastidx)
3348 if (++eindex == MAX_EVENTS)
3352 memcpy(estr, e, sizeof(gdth_evt_str));
3354 estr->event_source = 0;
3355 GDTH_UNLOCK_HA(ha, flags);
3358 static void gdth_clear_events()
3360 TRACE(("gdth_clear_events()"));
3362 eoldidx = elastidx = 0;
3363 ebuffer[0].event_source = 0;
3367 /* SCSI interface functions */
3369 static irqreturn_t gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
3371 register gdth_ha_str *ha;
3372 gdt6m_dpram_str *dp6m_ptr;
3373 gdt6_dpram_str *dp6_ptr;
3374 gdt2_dpram_str *dp2_ptr;
3381 TRACE(("gdth_interrupt() IRQ %d\n",irq));
3383 /* if polling and not from gdth_wait() -> return */
3385 if (!gdth_from_wait) {
3391 GDTH_LOCK_HA((gdth_ha_str *)dev_id,flags);
3394 /* search controller */
3395 if ((hanum = gdth_get_status(&IStatus,irq)) == -1) {
3396 /* spurious interrupt */
3398 GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
3402 #ifdef GDTH_STATISTICS
3406 ha = HADATA(gdth_ctr_tab[hanum]);
3407 if (ha->type == GDT_EISA) {
3408 if (IStatus & 0x80) { /* error flag */
3410 ha->status = inw(ha->bmic + MAILBOXREG+8);
3411 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
3412 } else /* no error */
3414 ha->info = inl(ha->bmic + MAILBOXREG+12);
3415 ha->service = inw(ha->bmic + MAILBOXREG+10);
3416 ha->info2 = inl(ha->bmic + MAILBOXREG+4);
3418 outb(0xff, ha->bmic + EDOORREG); /* acknowledge interrupt */
3419 outb(0x00, ha->bmic + SEMA1REG); /* reset status semaphore */
3420 } else if (ha->type == GDT_ISA) {
3421 dp2_ptr = (gdt2_dpram_str *)ha->brd;
3422 if (IStatus & 0x80) { /* error flag */
3424 ha->status = gdth_readw(&dp2_ptr->u.ic.Status);
3425 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
3426 } else /* no error */
3428 ha->info = gdth_readl(&dp2_ptr->u.ic.Info[0]);
3429 ha->service = gdth_readw(&dp2_ptr->u.ic.Service);
3430 ha->info2 = gdth_readl(&dp2_ptr->u.ic.Info[1]);
3432 gdth_writeb(0xff, &dp2_ptr->io.irqdel); /* acknowledge interrupt */
3433 gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index); /* reset command index */
3434 gdth_writeb(0, &dp2_ptr->io.Sema1); /* reset status semaphore */
3435 } else if (ha->type == GDT_PCI) {
3436 dp6_ptr = (gdt6_dpram_str *)ha->brd;
3437 if (IStatus & 0x80) { /* error flag */
3439 ha->status = gdth_readw(&dp6_ptr->u.ic.Status);
3440 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
3441 } else /* no error */
3443 ha->info = gdth_readl(&dp6_ptr->u.ic.Info[0]);
3444 ha->service = gdth_readw(&dp6_ptr->u.ic.Service);
3445 ha->info2 = gdth_readl(&dp6_ptr->u.ic.Info[1]);
3447 gdth_writeb(0xff, &dp6_ptr->io.irqdel); /* acknowledge interrupt */
3448 gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index); /* reset command index */
3449 gdth_writeb(0, &dp6_ptr->io.Sema1); /* reset status semaphore */
3450 } else if (ha->type == GDT_PCINEW) {
3451 if (IStatus & 0x80) { /* error flag */
3453 ha->status = inw(PTR2USHORT(&ha->plx->status));
3454 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
3457 ha->info = inl(PTR2USHORT(&ha->plx->info[0]));
3458 ha->service = inw(PTR2USHORT(&ha->plx->service));
3459 ha->info2 = inl(PTR2USHORT(&ha->plx->info[1]));
3461 outb(0xff, PTR2USHORT(&ha->plx->edoor_reg));
3462 outb(0x00, PTR2USHORT(&ha->plx->sema1_reg));
3463 } else if (ha->type == GDT_PCIMPR) {
3464 dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
3465 if (IStatus & 0x80) { /* error flag */
3467 ha->status = gdth_readw(&dp6m_ptr->i960r.status);
3468 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
3469 } else /* no error */
3471 ha->info = gdth_readl(&dp6m_ptr->i960r.info[0]);
3472 ha->service = gdth_readw(&dp6m_ptr->i960r.service);
3473 ha->info2 = gdth_readl(&dp6m_ptr->i960r.info[1]);
3476 if (IStatus == ASYNCINDEX) {
3477 if (ha->service != SCREENSERVICE &&
3478 (ha->fw_vers & 0xff) >= 0x1a) {
3480 gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.severity);
3481 for (i = 0; i < 256; ++i) {
3482 ha->dvr.event_string[i] = gdth_readb
3483 (&((gdt6m_dpram_str *)ha->brd)->i960r.evt_str[i]);
3484 if (ha->dvr.event_string[i] == 0)
3489 gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
3490 gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg);
3492 TRACE2(("gdth_interrupt() unknown controller type\n"));
3494 GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
3498 TRACE(("gdth_interrupt() index %d stat %d info %d\n",
3499 IStatus,ha->status,ha->info));
3501 if (gdth_from_wait) {
3503 wait_index = (int)IStatus;
3506 if (IStatus == ASYNCINDEX) {
3507 TRACE2(("gdth_interrupt() async. event\n"));
3508 gdth_async_event(hanum);
3510 GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
3515 if (IStatus == SPEZINDEX) {
3516 TRACE2(("Service unknown or not initialized !\n"));
3517 ha->dvr.size = sizeof(ha->dvr.eu.driver);
3518 ha->dvr.eu.driver.ionode = hanum;
3519 gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr);
3521 GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
3524 scp = ha->cmd_tab[IStatus-2].cmnd;
3525 Service = ha->cmd_tab[IStatus-2].service;
3526 ha->cmd_tab[IStatus-2].cmnd = UNUSED_CMND;
3527 if (scp == UNUSED_CMND) {
3528 TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus));
3529 ha->dvr.size = sizeof(ha->dvr.eu.driver);
3530 ha->dvr.eu.driver.ionode = hanum;
3531 ha->dvr.eu.driver.index = IStatus;
3532 gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr);
3534 GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
3537 if (scp == INTERNAL_CMND) {
3538 TRACE(("gdth_interrupt() answer to internal command\n"));
3540 GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
3544 TRACE(("gdth_interrupt() sync. status\n"));
3545 rval = gdth_sync_event(hanum,Service,IStatus,scp);
3547 GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
3549 gdth_putq(hanum,scp,scp->SCp.this_residual);
3550 } else if (rval == 1) {
3551 #if LINUX_VERSION_CODE >= 0x02053C
3552 GDTH_LOCK_SCSI_DONE(scp->device->host, flags);
3553 scp->scsi_done(scp);
3554 GDTH_UNLOCK_SCSI_DONE(scp->device->host, flags);
3555 #elif LINUX_VERSION_CODE >= 0x020503
3556 GDTH_LOCK_SCSI_DONE(scp->host, flags);
3557 scp->scsi_done(scp);
3558 GDTH_UNLOCK_SCSI_DONE(scp->host, flags);
3560 GDTH_LOCK_SCSI_DONE(flags);
3561 scp->scsi_done(scp);
3562 GDTH_UNLOCK_SCSI_DONE(flags);
3569 static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
3571 register gdth_ha_str *ha;
3576 ha = HADATA(gdth_ctr_tab[hanum]);
3578 TRACE(("gdth_sync_event() serv %d status %d\n",
3579 service,ha->status));
3581 if (service == SCREENSERVICE) {
3582 msg = (gdth_msg_str *)ha->pscratch;
3583 ha->scratch_busy = FALSE;
3584 TRACE(("len: %d, answer: %d, ext: %d, alen: %d\n",
3585 msg->msg_len,msg->msg_answer,msg->msg_ext,msg->msg_alen));
3587 if (!(msg->msg_answer && msg->msg_ext)) {
3588 msg->msg_text[msg->msg_len] = '\0';
3589 printk("%s",msg->msg_text);
3592 if (msg->msg_ext && !msg->msg_answer) {
3593 while (gdth_test_busy(hanum))
3595 cmdp->Service = SCREENSERVICE;
3596 cmdp->RequestBuffer = SCREEN_CMND;
3597 gdth_get_cmd_index(hanum);
3598 gdth_set_sema0(hanum);
3599 cmdp->OpCode = GDT_READ;
3600 cmdp->BoardNode = LOCALBOARD;
3601 cmdp->u.screen.reserved = 0;
3602 cmdp->u.screen.su.msg.msg_handle= msg->msg_handle;
3603 cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys;
3604 ha->scratch_busy = TRUE;
3605 ha->cmd_offs_dpmem = 0;
3606 ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr)
3609 gdth_copy_command(hanum);
3610 gdth_release_event(hanum);
3614 if (msg->msg_answer && msg->msg_alen) {
3615 /* default answers (getchar() not possible) */
3616 if (msg->msg_alen == 1) {
3619 msg->msg_text[0] = 0;
3623 msg->msg_text[0] = 1;
3624 msg->msg_text[1] = 0;
3627 msg->msg_answer = 0;
3628 while (gdth_test_busy(hanum))
3630 cmdp->Service = SCREENSERVICE;
3631 cmdp->RequestBuffer = SCREEN_CMND;
3632 gdth_get_cmd_index(hanum);
3633 gdth_set_sema0(hanum);
3634 cmdp->OpCode = GDT_WRITE;
3635 cmdp->BoardNode = LOCALBOARD;
3636 cmdp->u.screen.reserved = 0;
3637 cmdp->u.screen.su.msg.msg_handle= msg->msg_handle;
3638 cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys;
3639 ha->scratch_busy = TRUE;
3640 ha->cmd_offs_dpmem = 0;
3641 ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr)
3644 gdth_copy_command(hanum);
3645 gdth_release_event(hanum);
3651 #if LINUX_VERSION_CODE >= 0x02053C
3652 b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
3653 t = scp->device->id;
3655 b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
3658 if (scp->SCp.sent_command == -1 && b != ha->virt_bus) {
3659 ha->raw[BUS_L2P(ha,b)].io_cnt[t]--;
3661 /* cache or raw service */
3662 if (ha->status == S_BSY) {
3663 TRACE2(("Controller busy -> retry !\n"));
3664 if (scp->SCp.sent_command == GDT_MOUNT)
3665 scp->SCp.sent_command = GDT_CLUST_INFO;
3669 #if LINUX_VERSION_CODE >= 0x020400
3670 if (scp->SCp.Status == GDTH_MAP_SG)
3671 pci_unmap_sg(ha->pdev,scp->request_buffer,
3672 scp->use_sg,scp->SCp.Message);
3673 else if (scp->SCp.Status == GDTH_MAP_SINGLE)
3674 pci_unmap_single(ha->pdev,scp->SCp.dma_handle,
3675 scp->request_bufflen,scp->SCp.Message);
3676 if (scp->SCp.buffer)
3677 pci_unmap_single(ha->pdev,(dma_addr_t)scp->SCp.buffer,
3678 16,PCI_DMA_FROMDEVICE);
3680 if (ha->status == S_OK) {
3681 scp->SCp.Status = S_OK;
3682 scp->SCp.Message = ha->info;
3683 if (scp->SCp.sent_command != -1) {
3684 TRACE2(("gdth_sync_event(): special cmd 0x%x OK\n",
3685 scp->SCp.sent_command));
3686 /* special commands GDT_CLUST_INFO/GDT_MOUNT ? */
3687 if (scp->SCp.sent_command == GDT_CLUST_INFO) {
3688 ha->hdr[t].cluster_type = (unchar)ha->info;
3689 if (!(ha->hdr[t].cluster_type &
3691 /* NOT MOUNTED -> MOUNT */
3692 scp->SCp.sent_command = GDT_MOUNT;
3693 if (ha->hdr[t].cluster_type &
3695 /* cluster drive RESERVED (on the other node) */
3696 scp->SCp.phase = -2; /* reservation conflict */
3699 scp->SCp.sent_command = -1;
3702 if (scp->SCp.sent_command == GDT_MOUNT) {
3703 ha->hdr[t].cluster_type |= CLUSTER_MOUNTED;
3704 ha->hdr[t].media_changed = TRUE;
3705 } else if (scp->SCp.sent_command == GDT_UNMOUNT) {
3706 ha->hdr[t].cluster_type &= ~CLUSTER_MOUNTED;
3707 ha->hdr[t].media_changed = TRUE;
3709 scp->SCp.sent_command = -1;
3712 scp->SCp.this_residual = HIGH_PRI;
3715 /* RESERVE/RELEASE ? */
3716 if (scp->cmnd[0] == RESERVE) {
3717 ha->hdr[t].cluster_type |= CLUSTER_RESERVED;
3718 } else if (scp->cmnd[0] == RELEASE) {
3719 ha->hdr[t].cluster_type &= ~CLUSTER_RESERVED;
3721 scp->result = DID_OK << 16;
3722 scp->sense_buffer[0] = 0;
3725 scp->SCp.Status = ha->status;
3726 scp->SCp.Message = ha->info;
3728 if (scp->SCp.sent_command != -1) {
3729 TRACE2(("gdth_sync_event(): special cmd 0x%x error 0x%x\n",
3730 scp->SCp.sent_command, ha->status));
3731 if (scp->SCp.sent_command == GDT_SCAN_START ||
3732 scp->SCp.sent_command == GDT_SCAN_END) {
3733 scp->SCp.sent_command = -1;
3735 scp->SCp.this_residual = HIGH_PRI;
3738 memset((char*)scp->sense_buffer,0,16);
3739 scp->sense_buffer[0] = 0x70;
3740 scp->sense_buffer[2] = NOT_READY;
3741 scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
3742 } else if (service == CACHESERVICE) {
3743 if (ha->status == S_CACHE_UNKNOWN &&
3744 (ha->hdr[t].cluster_type &
3745 CLUSTER_RESERVE_STATE) == CLUSTER_RESERVE_STATE) {
3746 /* bus reset -> force GDT_CLUST_INFO */
3747 ha->hdr[t].cluster_type &= ~CLUSTER_RESERVED;
3749 memset((char*)scp->sense_buffer,0,16);
3750 if (ha->status == (ushort)S_CACHE_RESERV) {
3751 scp->result = (DID_OK << 16) | (RESERVATION_CONFLICT << 1);
3753 scp->sense_buffer[0] = 0x70;
3754 scp->sense_buffer[2] = NOT_READY;
3755 scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
3757 #if LINUX_VERSION_CODE >= 0x010300
3758 if (scp->done != gdth_scsi_done)
3761 ha->dvr.size = sizeof(ha->dvr.eu.sync);
3762 ha->dvr.eu.sync.ionode = hanum;
3763 ha->dvr.eu.sync.service = service;
3764 ha->dvr.eu.sync.status = ha->status;
3765 ha->dvr.eu.sync.info = ha->info;
3766 ha->dvr.eu.sync.hostdrive = t;
3767 if (ha->status >= 0x8000)
3768 gdth_store_event(ha, ES_SYNC, 0, &ha->dvr);
3770 gdth_store_event(ha, ES_SYNC, service, &ha->dvr);
3773 /* sense buffer filled from controller firmware (DMA) */
3774 if (ha->status != S_RAW_SCSI || ha->info >= 0x100) {
3775 scp->result = DID_BAD_TARGET << 16;
3777 scp->result = (DID_OK << 16) | ha->info;
3781 if (!scp->SCp.have_data_in)
3782 scp->SCp.have_data_in++;
3790 static char *async_cache_tab[] = {
3791 /* 0*/ "\011\000\002\002\002\004\002\006\004"
3792 "GDT HA %u, service %u, async. status %u/%lu unknown",
3793 /* 1*/ "\011\000\002\002\002\004\002\006\004"
3794 "GDT HA %u, service %u, async. status %u/%lu unknown",
3795 /* 2*/ "\005\000\002\006\004"
3796 "GDT HA %u, Host Drive %lu not ready",
3797 /* 3*/ "\005\000\002\006\004"
3798 "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",
3799 /* 4*/ "\005\000\002\006\004"
3800 "GDT HA %u, mirror update on Host Drive %lu failed",
3801 /* 5*/ "\005\000\002\006\004"
3802 "GDT HA %u, Mirror Drive %lu failed",
3803 /* 6*/ "\005\000\002\006\004"
3804 "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",
3805 /* 7*/ "\005\000\002\006\004"
3806 "GDT HA %u, Host Drive %lu write protected",
3807 /* 8*/ "\005\000\002\006\004"
3808 "GDT HA %u, media changed in Host Drive %lu",
3809 /* 9*/ "\005\000\002\006\004"
3810 "GDT HA %u, Host Drive %lu is offline",
3811 /*10*/ "\005\000\002\006\004"
3812 "GDT HA %u, media change of Mirror Drive %lu",
3813 /*11*/ "\005\000\002\006\004"
3814 "GDT HA %u, Mirror Drive %lu is write protected",
3815 /*12*/ "\005\000\002\006\004"
3816 "GDT HA %u, general error on Host Drive %lu. Please check the devices of this drive!",
3817 /*13*/ "\007\000\002\006\002\010\002"
3818 "GDT HA %u, Array Drive %u: Cache Drive %u failed",
3819 /*14*/ "\005\000\002\006\002"
3820 "GDT HA %u, Array Drive %u: FAIL state entered",
3821 /*15*/ "\005\000\002\006\002"
3822 "GDT HA %u, Array Drive %u: error",
3823 /*16*/ "\007\000\002\006\002\010\002"
3824 "GDT HA %u, Array Drive %u: failed drive replaced by Cache Drive %u",
3825 /*17*/ "\005\000\002\006\002"
3826 "GDT HA %u, Array Drive %u: parity build failed",
3827 /*18*/ "\005\000\002\006\002"
3828 "GDT HA %u, Array Drive %u: drive rebuild failed",
3829 /*19*/ "\005\000\002\010\002"
3830 "GDT HA %u, Test of Hot Fix %u failed",
3831 /*20*/ "\005\000\002\006\002"
3832 "GDT HA %u, Array Drive %u: drive build finished successfully",
3833 /*21*/ "\005\000\002\006\002"
3834 "GDT HA %u, Array Drive %u: drive rebuild finished successfully",
3835 /*22*/ "\007\000\002\006\002\010\002"
3836 "GDT HA %u, Array Drive %u: Hot Fix %u activated",
3837 /*23*/ "\005\000\002\006\002"
3838 "GDT HA %u, Host Drive %u: processing of i/o aborted due to serious drive error",
3839 /*24*/ "\005\000\002\010\002"
3840 "GDT HA %u, mirror update on Cache Drive %u completed",
3841 /*25*/ "\005\000\002\010\002"
3842 "GDT HA %u, mirror update on Cache Drive %lu failed",
3843 /*26*/ "\005\000\002\006\002"
3844 "GDT HA %u, Array Drive %u: drive rebuild started",
3845 /*27*/ "\005\000\002\012\001"
3846 "GDT HA %u, Fault bus %u: SHELF OK detected",
3847 /*28*/ "\005\000\002\012\001"
3848 "GDT HA %u, Fault bus %u: SHELF not OK detected",
3849 /*29*/ "\007\000\002\012\001\013\001"
3850 "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug started",
3851 /*30*/ "\007\000\002\012\001\013\001"
3852 "GDT HA %u, Fault bus %u, ID %u: new disk detected",
3853 /*31*/ "\007\000\002\012\001\013\001"
3854 "GDT HA %u, Fault bus %u, ID %u: old disk detected",
3855 /*32*/ "\007\000\002\012\001\013\001"
3856 "GDT HA %u, Fault bus %u, ID %u: plugging an active disk is invalid",
3857 /*33*/ "\007\000\002\012\001\013\001"
3858 "GDT HA %u, Fault bus %u, ID %u: invalid device detected",
3859 /*34*/ "\011\000\002\012\001\013\001\006\004"
3860 "GDT HA %u, Fault bus %u, ID %u: insufficient disk capacity (%lu MB required)",
3861 /*35*/ "\007\000\002\012\001\013\001"
3862 "GDT HA %u, Fault bus %u, ID %u: disk write protected",
3863 /*36*/ "\007\000\002\012\001\013\001"
3864 "GDT HA %u, Fault bus %u, ID %u: disk not available",
3865 /*37*/ "\007\000\002\012\001\006\004"
3866 "GDT HA %u, Fault bus %u: swap detected (%lu)",
3867 /*38*/ "\007\000\002\012\001\013\001"
3868 "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug finished successfully",
3869 /*39*/ "\007\000\002\012\001\013\001"
3870 "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug aborted due to user Hot Plug",
3871 /*40*/ "\007\000\002\012\001\013\001"
3872 "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug aborted",
3873 /*41*/ "\007\000\002\012\001\013\001"
3874 "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug for Hot Fix started",
3875 /*42*/ "\005\000\002\006\002"
3876 "GDT HA %u, Array Drive %u: drive build started",
3877 /*43*/ "\003\000\002"
3878 "GDT HA %u, DRAM parity error detected",
3879 /*44*/ "\005\000\002\006\002"
3880 "GDT HA %u, Mirror Drive %u: update started",
3881 /*45*/ "\007\000\002\006\002\010\002"
3882 "GDT HA %u, Mirror Drive %u: Hot Fix %u activated",
3883 /*46*/ "\005\000\002\006\002"
3884 "GDT HA %u, Array Drive %u: no matching Pool Hot Fix Drive available",
3885 /*47*/ "\005\000\002\006\002"
3886 "GDT HA %u, Array Drive %u: Pool Hot Fix Drive available",
3887 /*48*/ "\005\000\002\006\002"
3888 "GDT HA %u, Mirror Drive %u: no matching Pool Hot Fix Drive available",
3889 /*49*/ "\005\000\002\006\002"
3890 "GDT HA %u, Mirror Drive %u: Pool Hot Fix Drive available",
3891 /*50*/ "\007\000\002\012\001\013\001"
3892 "GDT HA %u, SCSI bus %u, ID %u: IGNORE_WIDE_RESIDUE message received",
3893 /*51*/ "\005\000\002\006\002"
3894 "GDT HA %u, Array Drive %u: expand started",
3895 /*52*/ "\005\000\002\006\002"
3896 "GDT HA %u, Array Drive %u: expand finished successfully",
3897 /*53*/ "\005\000\002\006\002"
3898 "GDT HA %u, Array Drive %u: expand failed",
3899 /*54*/ "\003\000\002"
3900 "GDT HA %u, CPU temperature critical",
3901 /*55*/ "\003\000\002"
3902 "GDT HA %u, CPU temperature OK",
3903 /*56*/ "\005\000\002\006\004"
3904 "GDT HA %u, Host drive %lu created",
3905 /*57*/ "\005\000\002\006\002"
3906 "GDT HA %u, Array Drive %u: expand restarted",
3907 /*58*/ "\005\000\002\006\002"
3908 "GDT HA %u, Array Drive %u: expand stopped",
3909 /*59*/ "\005\000\002\010\002"
3910 "GDT HA %u, Mirror Drive %u: drive build quited",
3911 /*60*/ "\005\000\002\006\002"
3912 "GDT HA %u, Array Drive %u: parity build quited",
3913 /*61*/ "\005\000\002\006\002"
3914 "GDT HA %u, Array Drive %u: drive rebuild quited",
3915 /*62*/ "\005\000\002\006\002"
3916 "GDT HA %u, Array Drive %u: parity verify started",
3917 /*63*/ "\005\000\002\006\002"
3918 "GDT HA %u, Array Drive %u: parity verify done",
3919 /*64*/ "\005\000\002\006\002"
3920 "GDT HA %u, Array Drive %u: parity verify failed",
3921 /*65*/ "\005\000\002\006\002"
3922 "GDT HA %u, Array Drive %u: parity error detected",
3923 /*66*/ "\005\000\002\006\002"
3924 "GDT HA %u, Array Drive %u: parity verify quited",
3925 /*67*/ "\005\000\002\006\002"
3926 "GDT HA %u, Host Drive %u reserved",
3927 /*68*/ "\005\000\002\006\002"
3928 "GDT HA %u, Host Drive %u mounted and released",
3929 /*69*/ "\005\000\002\006\002"
3930 "GDT HA %u, Host Drive %u released",
3931 /*70*/ "\003\000\002"
3932 "GDT HA %u, DRAM error detected and corrected with ECC",
3933 /*71*/ "\003\000\002"
3934 "GDT HA %u, Uncorrectable DRAM error detected with ECC",
3935 /*72*/ "\011\000\002\012\001\013\001\014\001"
3936 "GDT HA %u, SCSI bus %u, ID %u, LUN %u: reassigning block",
3937 /*73*/ "\005\000\002\006\002"
3938 "GDT HA %u, Host drive %u resetted locally",
3939 /*74*/ "\005\000\002\006\002"
3940 "GDT HA %u, Host drive %u resetted remotely",
3941 /*75*/ "\003\000\002"
3942 "GDT HA %u, async. status 75 unknown",
3946 static int gdth_async_event(int hanum)
3953 ha = HADATA(gdth_ctr_tab[hanum]);
3955 msg = (gdth_msg_str *)ha->pscratch;
3956 TRACE2(("gdth_async_event() ha %d serv %d\n",
3957 hanum,ha->service));
3959 if (ha->service == SCREENSERVICE) {
3960 if (ha->status == MSG_REQUEST) {
3961 while (gdth_test_busy(hanum))
3963 cmdp->Service = SCREENSERVICE;
3964 cmdp->RequestBuffer = SCREEN_CMND;
3965 cmd_index = gdth_get_cmd_index(hanum);
3966 gdth_set_sema0(hanum);
3967 cmdp->OpCode = GDT_READ;
3968 cmdp->BoardNode = LOCALBOARD;
3969 cmdp->u.screen.reserved = 0;
3970 cmdp->u.screen.su.msg.msg_handle= MSG_INV_HANDLE;
3971 cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys;
3972 ha->scratch_busy = TRUE;
3973 ha->cmd_offs_dpmem = 0;
3974 ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr)
3977 gdth_copy_command(hanum);
3978 if (ha->type == GDT_EISA)
3979 printk("[EISA slot %d] ",(ushort)ha->brd_phys);
3980 else if (ha->type == GDT_ISA)
3981 printk("[DPMEM 0x%4X] ",(ushort)ha->brd_phys);
3983 printk("[PCI %d/%d] ",(ushort)(ha->brd_phys>>8),
3984 (ushort)((ha->brd_phys>>3)&0x1f));
3985 gdth_release_event(hanum);
3989 if (ha->type == GDT_PCIMPR &&
3990 (ha->fw_vers & 0xff) >= 0x1a) {
3992 ha->dvr.eu.async.ionode = hanum;
3993 ha->dvr.eu.async.status = ha->status;
3994 /* severity and event_string already set! */
3996 ha->dvr.size = sizeof(ha->dvr.eu.async);
3997 ha->dvr.eu.async.ionode = hanum;
3998 ha->dvr.eu.async.service = ha->service;
3999 ha->dvr.eu.async.status = ha->status;
4000 ha->dvr.eu.async.info = ha->info;
4001 *(ulong32 *)ha->dvr.eu.async.scsi_coord = ha->info2;
4003 gdth_store_event( ha, ES_ASYNC, ha->service, &ha->dvr );
4004 gdth_log_event( &ha->dvr, NULL );
4006 /* new host drive from expand? */
4007 if (ha->service == CACHESERVICE && ha->status == 56) {
4008 TRACE2(("gdth_async_event(): new host drive %d created\n",
4010 /* gdth_analyse_hdrive(hanum, (ushort)ha->info); */
4016 static void gdth_log_event(gdth_evt_data *dvr, char *buffer)
4018 gdth_stackframe stack;
4022 TRACE2(("gdth_log_event()\n"));
4023 if (dvr->size == 0) {
4024 if (buffer == NULL) {
4025 printk("Adapter %d: %s\n",dvr->eu.async.ionode,dvr->event_string);
4027 sprintf(buffer,"Adapter %d: %s\n",
4028 dvr->eu.async.ionode,dvr->event_string);
4030 } else if (dvr->eu.async.service == CACHESERVICE &&
4031 INDEX_OK(dvr->eu.async.status, async_cache_tab)) {
4032 TRACE2(("GDT: Async. event cache service, event no.: %d\n",
4033 dvr->eu.async.status));
4035 f = async_cache_tab[dvr->eu.async.status];
4037 /* i: parameter to push, j: stack element to fill */
4038 for (j=0,i=1; i < f[0]; i+=2) {
4041 stack.b[j++] = *(ulong32*)&dvr->eu.stream[(int)f[i]];
4044 stack.b[j++] = *(ushort*)&dvr->eu.stream[(int)f[i]];
4047 stack.b[j++] = *(unchar*)&dvr->eu.stream[(int)f[i]];
4054 if (buffer == NULL) {
4055 printk(&f[(int)f[0]],stack);
4058 sprintf(buffer,&f[(int)f[0]],stack);
4062 if (buffer == NULL) {
4063 printk("GDT HA %u, Unknown async. event service %d event no. %d\n",
4064 dvr->eu.async.ionode,dvr->eu.async.service,dvr->eu.async.status);
4066 sprintf(buffer,"GDT HA %u, Unknown async. event service %d event no. %d",
4067 dvr->eu.async.ionode,dvr->eu.async.service,dvr->eu.async.status);
4072 #ifdef GDTH_STATISTICS
4073 void gdth_timeout(ulong data)
4081 ha = HADATA(gdth_ctr_tab[hanum]);
4082 GDTH_LOCK_HA(ha, flags);
4084 for (act_stats=0,i=0; i<GDTH_MAXCMDS; ++i)
4085 if (ha->cmd_tab[i].cmnd != UNUSED_CMND)
4088 for (act_rq=0,nscp=ha->req_first; nscp; nscp=(Scsi_Cmnd*)nscp->SCp.ptr)
4091 TRACE2(("gdth_to(): ints %d, ios %d, act_stats %d, act_rq %d\n",
4092 act_ints, act_ios, act_stats, act_rq));
4093 act_ints = act_ios = 0;
4095 gdth_timer.expires = jiffies + 30 * HZ;
4096 add_timer(&gdth_timer);
4097 GDTH_UNLOCK_HA(ha, flags);
4101 GDTH_INITFUNC(void, internal_setup(char *str,int *ints))
4104 char *cur_str, *argv;
4106 TRACE2(("internal_setup() str %s ints[0] %d\n",
4107 str ? str:"NULL", ints ? ints[0]:0));
4109 /* read irq[] from ints[] */
4115 for (i = 0; i < argc; ++i)
4120 /* analyse string */
4122 while (argv && (cur_str = strchr(argv, ':'))) {
4123 int val = 0, c = *++cur_str;
4125 if (c == 'n' || c == 'N')
4127 else if (c == 'y' || c == 'Y')
4130 val = (int)simple_strtoul(cur_str, NULL, 0);
4132 if (!strncmp(argv, "disable:", 8))
4134 else if (!strncmp(argv, "reserve_mode:", 13))
4136 else if (!strncmp(argv, "reverse_scan:", 13))
4138 else if (!strncmp(argv, "hdr_channel:", 12))
4140 else if (!strncmp(argv, "max_ids:", 8))
4142 else if (!strncmp(argv, "rescan:", 7))
4144 else if (!strncmp(argv, "virt_ctr:", 9))
4146 else if (!strncmp(argv, "shared_access:", 14))
4147 shared_access = val;
4148 else if (!strncmp(argv, "probe_eisa_isa:", 15))
4149 probe_eisa_isa = val;
4150 else if (!strncmp(argv, "reserve_list:", 13)) {
4151 reserve_list[0] = val;
4152 for (i = 1; i < MAX_RES_ARGS; i++) {
4153 cur_str = strchr(cur_str, ',');
4156 if (!isdigit((int)*++cur_str)) {
4161 (int)simple_strtoul(cur_str, NULL, 0);
4169 if ((argv = strchr(argv, ',')))
4174 GDTH_INITFUNC(int, option_setup(char *str))
4180 TRACE2(("option_setup() str %s\n", str ? str:"NULL"));
4182 while (cur && isdigit(*cur) && i <= MAXHA) {
4183 ints[i++] = simple_strtoul(cur, NULL, 0);
4184 if ((cur = strchr(cur, ',')) != NULL) cur++;
4188 internal_setup(cur, ints);
4192 GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
4194 struct Scsi_Host *shp;
4198 int i,hanum,cnt,ctr;
4203 printk("GDT: This driver contains debugging information !! Trace level = %d\n",
4205 printk(" Destination of debugging information: ");
4208 printk("Serial port COM2\n");
4210 printk("Serial port COM1\n");
4213 printk("Console\n");
4218 TRACE(("gdth_detect()\n"));
4221 printk("GDT: Controller driver disabled from command line !\n");
4225 printk("GDT: Storage RAID Controller Driver. Version: %s \n",GDTH_VERSION_STR);
4226 /* initializations */
4227 gdth_polling = TRUE; b = 0;
4228 gdth_clear_events();
4230 /* As default we do not probe for EISA or ISA controllers */
4231 if (probe_eisa_isa) {
4232 /* scanning for controllers, at first: ISA controller */
4233 for (isa_bios=0xc8000UL; isa_bios<=0xd8000UL; isa_bios+=0x8000UL) {
4234 dma_addr_t scratch_dma_handle;
4236 if (gdth_ctr_count >= MAXHA)
4238 if (gdth_search_isa(isa_bios)) { /* controller found */
4239 shp = scsi_register(shtp,sizeof(gdth_ext_str));
4244 if (!gdth_init_isa(isa_bios,ha)) {
4245 scsi_unregister(shp);
4251 /* controller found and initialized */
4252 printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n",
4253 isa_bios,ha->irq,ha->drq);
4255 #if LINUX_VERSION_CODE >= 0x010346
4256 if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha))
4258 if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth"))
4261 printk("GDT-ISA: Unable to allocate IRQ\n");
4262 scsi_unregister(shp);
4265 if (request_dma(ha->drq,"gdth")) {
4266 printk("GDT-ISA: Unable to allocate DMA channel\n");
4267 #if LINUX_VERSION_CODE >= 0x010346
4268 free_irq(ha->irq,ha);
4272 scsi_unregister(shp);
4275 set_dma_mode(ha->drq,DMA_MODE_CASCADE);
4276 enable_dma(ha->drq);
4277 shp->unchecked_isa_dma = 1;
4279 shp->dma_channel = ha->drq;
4280 hanum = gdth_ctr_count;
4281 gdth_ctr_tab[gdth_ctr_count++] = shp;
4282 gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
4284 NUMDATA(shp)->hanum = (ushort)hanum;
4285 NUMDATA(shp)->busnum= 0;
4287 ha->pccb = CMDDATA(shp);
4289 #if LINUX_VERSION_CODE >= 0x020400
4291 ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH,
4292 &scratch_dma_handle);
4293 ha->scratch_phys = (ulong32)scratch_dma_handle;
4295 ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
4297 ha->scratch_phys = virt_to_bus(ha->pscratch);
4299 ha->scratch_busy = FALSE;
4300 ha->req_first = NULL;
4301 ha->tid_cnt = MAX_HDRIVES;
4302 if (max_ids > 0 && max_ids < ha->tid_cnt)
4303 ha->tid_cnt = max_ids;
4304 for (i=0; i<GDTH_MAXCMDS; ++i)
4305 ha->cmd_tab[i].cmnd = UNUSED_CMND;
4306 ha->scan_mode = rescan ? 0x10 : 0;
4308 if (ha->pscratch == NULL || !gdth_search_drives(hanum)) {
4309 printk("GDT-ISA: Error during device scan\n");
4312 if (ha->pscratch != NULL) {
4313 #if LINUX_VERSION_CODE >= 0x020400
4314 pci_free_consistent(ha->pdev, GDTH_SCRATCH,
4315 ha->pscratch, ha->scratch_phys);
4317 scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
4320 #if LINUX_VERSION_CODE >= 0x010346
4321 free_irq(ha->irq,ha);
4325 scsi_unregister(shp);
4328 if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
4329 hdr_channel = ha->bus_cnt;
4330 ha->virt_bus = hdr_channel;
4332 #if LINUX_VERSION_CODE >= 0x020000
4333 shp->max_id = ha->tid_cnt;
4334 shp->max_lun = MAXLUN;
4335 shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
4340 /* register addit. SCSI channels as virtual controllers */
4341 for (b = 1; b < ha->bus_cnt + 1; ++b) {
4342 shp = scsi_register(shtp,sizeof(gdth_num_str));
4343 shp->unchecked_isa_dma = 1;
4345 shp->dma_channel = ha->drq;
4346 gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
4347 NUMDATA(shp)->hanum = (ushort)hanum;
4348 NUMDATA(shp)->busnum = b;
4352 GDTH_INIT_LOCK_HA(ha);
4353 gdth_enable_int(hanum);
4354 #endif /* !__ia64__ */
4358 /* scanning for EISA controllers */
4359 for (eisa_slot=0x1000; eisa_slot<=0x8000; eisa_slot+=0x1000) {
4360 dma_addr_t scratch_dma_handle;
4362 if (gdth_ctr_count >= MAXHA)
4364 if (gdth_search_eisa(eisa_slot)) { /* controller found */
4365 shp = scsi_register(shtp,sizeof(gdth_ext_str));
4370 if (!gdth_init_eisa(eisa_slot,ha)) {
4371 scsi_unregister(shp);
4374 /* controller found and initialized */
4375 printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n",
4376 eisa_slot>>12,ha->irq);
4378 #if LINUX_VERSION_CODE >= 0x010346
4379 if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha))
4381 if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth"))
4384 printk("GDT-EISA: Unable to allocate IRQ\n");
4385 scsi_unregister(shp);
4388 shp->unchecked_isa_dma = 0;
4390 shp->dma_channel = 0xff;
4391 hanum = gdth_ctr_count;
4392 gdth_ctr_tab[gdth_ctr_count++] = shp;
4393 gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
4395 NUMDATA(shp)->hanum = (ushort)hanum;
4396 NUMDATA(shp)->busnum= 0;
4397 TRACE2(("EISA detect Bus 0: hanum %d\n",
4398 NUMDATA(shp)->hanum));
4400 ha->pccb = CMDDATA(shp);
4402 #if LINUX_VERSION_CODE >= 0x020400
4404 ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH,
4405 &scratch_dma_handle);
4406 ha->scratch_phys = (ulong32) scratch_dma_handle;
4408 pci_map_single(ha->pdev,ha->pccb,
4409 sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
4411 ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
4413 ha->scratch_phys = virt_to_bus(ha->pscratch);
4414 ha->ccb_phys = virt_to_bus(ha->pccb);
4416 ha->scratch_busy = FALSE;
4417 ha->req_first = NULL;
4418 ha->tid_cnt = MAX_HDRIVES;
4419 if (max_ids > 0 && max_ids < ha->tid_cnt)
4420 ha->tid_cnt = max_ids;
4421 for (i=0; i<GDTH_MAXCMDS; ++i)
4422 ha->cmd_tab[i].cmnd = UNUSED_CMND;
4423 ha->scan_mode = rescan ? 0x10 : 0;
4425 if (ha->pscratch == NULL || !gdth_search_drives(hanum)) {
4426 printk("GDT-EISA: Error during device scan\n");
4429 if (ha->pscratch != NULL) {
4430 #if LINUX_VERSION_CODE >= 0x020400
4431 pci_free_consistent(ha->pdev, GDTH_SCRATCH,
4432 ha->pscratch, ha->scratch_phys);
4433 pci_unmap_single(ha->pdev,ha->ccb_phys,
4434 sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
4436 scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
4439 #if LINUX_VERSION_CODE >= 0x010346
4440 free_irq(ha->irq,ha);
4444 scsi_unregister(shp);
4447 if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
4448 hdr_channel = ha->bus_cnt;
4449 ha->virt_bus = hdr_channel;
4451 #if LINUX_VERSION_CODE >= 0x020000
4452 shp->max_id = ha->tid_cnt;
4453 shp->max_lun = MAXLUN;
4454 shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
4459 /* register addit. SCSI channels as virtual controllers */
4460 for (b = 1; b < ha->bus_cnt + 1; ++b) {
4461 shp = scsi_register(shtp,sizeof(gdth_num_str));
4462 shp->unchecked_isa_dma = 0;
4464 shp->dma_channel = 0xff;
4465 gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
4466 NUMDATA(shp)->hanum = (ushort)hanum;
4467 NUMDATA(shp)->busnum = b;
4471 GDTH_INIT_LOCK_HA(ha);
4472 gdth_enable_int(hanum);
4477 /* scanning for PCI controllers */
4478 #if LINUX_VERSION_CODE < 0x2015C
4479 if (pcibios_present())
4482 gdth_pci_str pcistr[MAXHA];
4484 cnt = gdth_search_pci(pcistr);
4485 printk("GDT: Found %d PCI Storage RAID Controllers\n",cnt);
4486 gdth_sort_pci(pcistr,cnt);
4487 for (ctr = 0; ctr < cnt; ++ctr) {
4488 dma_addr_t scratch_dma_handle;
4490 if (gdth_ctr_count >= MAXHA)
4492 shp = scsi_register(shtp,sizeof(gdth_ext_str));
4497 if (!gdth_init_pci(&pcistr[ctr],ha)) {
4498 scsi_unregister(shp);
4501 /* controller found and initialized */
4502 printk("GDT CTR%d: Configuring GDT-PCI HA at %d/%d IRQ %u\n",
4503 ctr,pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq);
4505 #if LINUX_VERSION_CODE >= 0x010346
4506 if (request_irq(ha->irq, gdth_interrupt,
4507 SA_INTERRUPT|SA_SHIRQ, "gdth", ha))
4509 if (request_irq(ha->irq, gdth_interrupt,
4510 SA_INTERRUPT|SA_SHIRQ, "gdth"))
4513 printk("GDT-PCI: Unable to allocate IRQ\n");
4514 scsi_unregister(shp);
4517 shp->unchecked_isa_dma = 0;
4519 shp->dma_channel = 0xff;
4520 hanum = gdth_ctr_count;
4521 gdth_ctr_tab[gdth_ctr_count++] = shp;
4522 gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
4524 NUMDATA(shp)->hanum = (ushort)hanum;
4525 NUMDATA(shp)->busnum= 0;
4527 ha->pccb = CMDDATA(shp);
4529 #if LINUX_VERSION_CODE >= 0x020400
4530 ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH,
4531 &scratch_dma_handle);
4532 ha->scratch_phys = (ulong32)scratch_dma_handle;
4534 ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
4536 ha->scratch_phys = virt_to_bus(ha->pscratch);
4538 ha->scratch_busy = FALSE;
4539 ha->req_first = NULL;
4540 ha->tid_cnt = pcistr[ctr].device_id >= 0x200 ? MAXID : MAX_HDRIVES;
4541 if (max_ids > 0 && max_ids < ha->tid_cnt)
4542 ha->tid_cnt = max_ids;
4543 for (i=0; i<GDTH_MAXCMDS; ++i)
4544 ha->cmd_tab[i].cmnd = UNUSED_CMND;
4545 ha->scan_mode = rescan ? 0x10 : 0;
4547 if (ha->pscratch == NULL || !gdth_search_drives(hanum)) {
4548 printk("GDT-PCI: Error during device scan\n");
4551 if (ha->pscratch != NULL) {
4552 #if LINUX_VERSION_CODE >= 0x020400
4553 pci_free_consistent(ha->pdev, GDTH_SCRATCH,
4554 ha->pscratch, ha->scratch_phys);
4556 scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
4559 #if LINUX_VERSION_CODE >= 0x010346
4560 free_irq(ha->irq,ha);
4564 scsi_unregister(shp);
4567 if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
4568 hdr_channel = ha->bus_cnt;
4569 ha->virt_bus = hdr_channel;
4571 #if LINUX_VERSION_CODE >= 0x020000
4572 shp->max_id = ha->tid_cnt;
4573 shp->max_lun = MAXLUN;
4574 shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
4579 /* register addit. SCSI channels as virtual controllers */
4580 for (b = 1; b < ha->bus_cnt + 1; ++b) {
4581 shp = scsi_register(shtp,sizeof(gdth_num_str));
4582 shp->unchecked_isa_dma = 0;
4584 shp->dma_channel = 0xff;
4585 gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
4586 NUMDATA(shp)->hanum = (ushort)hanum;
4587 NUMDATA(shp)->busnum = b;
4591 GDTH_INIT_LOCK_HA(ha);
4592 gdth_enable_int(hanum);
4596 TRACE2(("gdth_detect() %d controller detected\n",gdth_ctr_count));
4597 if (gdth_ctr_count > 0) {
4598 #ifdef GDTH_STATISTICS
4599 TRACE2(("gdth_detect(): Initializing timer !\n"));
4600 init_timer(&gdth_timer);
4601 gdth_timer.expires = jiffies + HZ;
4602 gdth_timer.data = 0L;
4603 gdth_timer.function = gdth_timeout;
4604 add_timer(&gdth_timer);
4606 #ifdef GDTH_IOCTL_CHRDEV
4607 major = register_chrdev(0,"gdth",&gdth_fops);
4609 #if LINUX_VERSION_CODE >= 0x020100
4610 register_reboot_notifier(&gdth_notifier);
4613 gdth_polling = FALSE;
4614 return gdth_ctr_vcount;
4618 int gdth_release(struct Scsi_Host *shp)
4623 TRACE2(("gdth_release()\n"));
4624 if (NUMDATA(shp)->busnum == 0) {
4625 hanum = NUMDATA(shp)->hanum;
4626 ha = HADATA(gdth_ctr_tab[hanum]);
4627 #if LINUX_VERSION_CODE >= 0x010300
4632 #if LINUX_VERSION_CODE >= 0x010346
4633 free_irq(shp->irq,ha);
4639 if (shp->dma_channel != 0xff) {
4640 free_dma(shp->dma_channel);
4643 #if LINUX_VERSION_CODE >= 0x020400
4644 pci_free_consistent(ha->pdev, GDTH_SCRATCH,
4645 ha->pscratch, ha->scratch_phys);
4647 pci_unmap_single(ha->pdev,ha->ccb_phys,
4648 sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
4650 scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
4652 gdth_ctr_released++;
4653 TRACE2(("gdth_release(): HA %d of %d\n",
4654 gdth_ctr_released, gdth_ctr_count));
4656 if (gdth_ctr_released == gdth_ctr_count) {
4657 #ifdef GDTH_STATISTICS
4658 del_timer(&gdth_timer);
4660 #ifdef GDTH_IOCTL_CHRDEV
4661 unregister_chrdev(major,"gdth");
4663 #if LINUX_VERSION_CODE >= 0x020100
4664 unregister_reboot_notifier(&gdth_notifier);
4669 scsi_unregister(shp);
4674 static const char *gdth_ctr_name(int hanum)
4678 TRACE2(("gdth_ctr_name()\n"));
4680 ha = HADATA(gdth_ctr_tab[hanum]);
4682 if (ha->type == GDT_EISA) {
4683 switch (ha->stype) {
4685 return("GDT3000/3020");
4687 return("GDT3000A/3020A/3050A");
4689 return("GDT3000B/3010A");
4691 } else if (ha->type == GDT_ISA) {
4692 return("GDT2000/2020");
4693 } else if (ha->type == GDT_PCI) {
4694 switch (ha->stype) {
4695 case PCI_DEVICE_ID_VORTEX_GDT60x0:
4696 return("GDT6000/6020/6050");
4697 case PCI_DEVICE_ID_VORTEX_GDT6000B:
4698 return("GDT6000B/6010");
4701 /* new controllers (GDT_PCINEW, GDT_PCIMPR, ..) use board_info IOCTL! */
4706 const char *gdth_info(struct Scsi_Host *shp)
4711 TRACE2(("gdth_info()\n"));
4712 hanum = NUMDATA(shp)->hanum;
4713 ha = HADATA(gdth_ctr_tab[hanum]);
4715 return ((const char *)ha->binfo.type_string);
4718 /* old error handling */
4719 int gdth_abort(Scsi_Cmnd *scp)
4721 TRACE2(("gdth_abort() reason %d\n",scp->abort_reason));
4722 return SCSI_ABORT_SNOOZE;
4725 #if LINUX_VERSION_CODE >= 0x010346
4726 int gdth_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
4728 int gdth_reset(Scsi_Cmnd *scp)
4731 TRACE2(("gdth_reset()\n"));
4732 return SCSI_RESET_PUNT;
4735 #if LINUX_VERSION_CODE >= 0x02015F
4736 /* new error handling */
4737 int gdth_eh_abort(Scsi_Cmnd *scp)
4739 TRACE2(("gdth_eh_abort()\n"));
4743 int gdth_eh_device_reset(Scsi_Cmnd *scp)
4745 TRACE2(("gdth_eh_device_reset()\n"));
4749 int gdth_eh_bus_reset(Scsi_Cmnd *scp)
4757 TRACE2(("gdth_eh_bus_reset()\n"));
4758 #if LINUX_VERSION_CODE >= 0x02053C
4759 hanum = NUMDATA(scp->device->host)->hanum;
4760 b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
4762 hanum = NUMDATA(scp->host)->hanum;
4763 b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
4765 ha = HADATA(gdth_ctr_tab[hanum]);
4767 /* clear command tab */
4768 GDTH_LOCK_HA(ha, flags);
4769 for (i = 0; i < GDTH_MAXCMDS; ++i) {
4770 cmnd = ha->cmd_tab[i].cmnd;
4771 #if LINUX_VERSION_CODE >= 0x02053C
4772 if (!SPECIAL_SCP(cmnd) && cmnd->device->channel == b)
4774 if (!SPECIAL_SCP(cmnd) && cmnd->channel == b)
4776 ha->cmd_tab[i].cmnd = UNUSED_CMND;
4778 GDTH_UNLOCK_HA(ha, flags);
4780 if (b == ha->virt_bus) {
4782 for (i = 0; i < MAX_HDRIVES; ++i) {
4783 if (ha->hdr[i].present) {
4784 GDTH_LOCK_HA(ha, flags);
4785 gdth_polling = TRUE;
4786 while (gdth_test_busy(hanum))
4788 if (gdth_internal_cmd(hanum, CACHESERVICE,
4789 GDT_CLUST_RESET, i, 0, 0))
4790 ha->hdr[i].cluster_type &= ~CLUSTER_RESERVED;
4791 gdth_polling = FALSE;
4792 GDTH_UNLOCK_HA(ha, flags);
4797 GDTH_LOCK_HA(ha, flags);
4798 for (i = 0; i < MAXID; ++i)
4799 ha->raw[BUS_L2P(ha,b)].io_cnt[i] = 0;
4800 gdth_polling = TRUE;
4801 while (gdth_test_busy(hanum))
4803 gdth_internal_cmd(hanum, SCSIRAWSERVICE, GDT_RESET_BUS,
4804 BUS_L2P(ha,b), 0, 0);
4805 gdth_polling = FALSE;
4806 GDTH_UNLOCK_HA(ha, flags);
4811 int gdth_eh_host_reset(Scsi_Cmnd *scp)
4813 TRACE2(("gdth_eh_host_reset()\n"));
4819 #if LINUX_VERSION_CODE >= 0x020503
4820 int gdth_bios_param(struct scsi_device *sdev,struct block_device *bdev,sector_t cap,int *ip)
4821 #elif LINUX_VERSION_CODE >= 0x010300
4822 int gdth_bios_param(Disk *disk,kdev_t dev,int *ip)
4824 int gdth_bios_param(Disk *disk,int dev,int *ip)
4830 struct scsi_device *sd;
4833 #if LINUX_VERSION_CODE >= 0x020503
4838 capacity = disk->capacity;
4840 hanum = NUMDATA(sd->host)->hanum;
4841 b = virt_ctr ? NUMDATA(sd->host)->busnum : sd->channel;
4843 TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", hanum, b, t));
4844 ha = HADATA(gdth_ctr_tab[hanum]);
4846 if (b != ha->virt_bus || ha->hdr[t].heads == 0) {
4847 /* raw device or host drive without mapping information */
4848 TRACE2(("Evaluate mapping\n"));
4849 gdth_eval_mapping(capacity,&ip[2],&ip[0],&ip[1]);
4851 ip[0] = ha->hdr[t].heads;
4852 ip[1] = ha->hdr[t].secs;
4853 ip[2] = capacity / ip[0] / ip[1];
4856 TRACE2(("gdth_bios_param(): %d heads, %d secs, %d cyls\n",
4857 ip[0],ip[1],ip[2]));
4862 int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *))
4867 TRACE(("gdth_queuecommand() cmd 0x%x\n", scp->cmnd[0]));
4869 scp->scsi_done = (void *)done;
4870 scp->SCp.have_data_in = 1;
4871 scp->SCp.phase = -1;
4872 scp->SCp.sent_command = -1;
4873 scp->SCp.Status = GDTH_MAP_NONE;
4874 scp->SCp.buffer = (struct scatterlist *)NULL;
4875 #if LINUX_VERSION_CODE >= 0x02053C
4876 hanum = NUMDATA(scp->device->host)->hanum;
4878 hanum = NUMDATA(scp->host)->hanum;
4880 #ifdef GDTH_STATISTICS
4884 priority = DEFAULT_PRI;
4885 #if LINUX_VERSION_CODE >= 0x010300
4886 if (scp->done == gdth_scsi_done)
4887 priority = scp->SCp.this_residual;
4889 gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6);
4890 gdth_putq( hanum, scp, priority );
4895 #ifdef GDTH_IOCTL_CHRDEV
4896 static int gdth_open(struct inode *inode, struct file *filep)
4898 TRACE(("gdth_open()\n"));
4902 static int gdth_close(struct inode *inode, struct file *filep)
4904 TRACE(("gdth_close()\n"));
4908 static int ioc_event(unsigned long arg)
4910 gdth_ioctl_event evt;
4914 if (copy_from_user(&evt, (char *)arg, sizeof(gdth_ioctl_event)) ||
4915 evt.ionode >= gdth_ctr_count)
4917 ha = HADATA(gdth_ctr_tab[evt.ionode]);
4919 if (evt.erase == 0xff) {
4920 if (evt.event.event_source == ES_TEST)
4921 evt.event.event_data.size=sizeof(evt.event.event_data.eu.test);
4922 else if (evt.event.event_source == ES_DRIVER)
4923 evt.event.event_data.size=sizeof(evt.event.event_data.eu.driver);
4924 else if (evt.event.event_source == ES_SYNC)
4925 evt.event.event_data.size=sizeof(evt.event.event_data.eu.sync);
4927 evt.event.event_data.size=sizeof(evt.event.event_data.eu.async);
4928 GDTH_LOCK_HA(ha, flags);
4929 gdth_store_event(ha, evt.event.event_source, evt.event.event_idx,
4930 &evt.event.event_data);
4931 GDTH_UNLOCK_HA(ha, flags);
4932 } else if (evt.erase == 0xfe) {
4933 gdth_clear_events();
4934 } else if (evt.erase == 0) {
4935 evt.handle = gdth_read_event(ha, evt.handle, &evt.event);
4937 gdth_readapp_event(ha, evt.erase, &evt.event);
4939 if (copy_to_user((char *)arg, &evt, sizeof(gdth_ioctl_event)))
4944 static int ioc_lockdrv(unsigned long arg)
4946 gdth_ioctl_lockdrv ldrv;
4951 if (copy_from_user(&ldrv, (char *)arg, sizeof(gdth_ioctl_lockdrv)) ||
4952 ldrv.ionode >= gdth_ctr_count)
4954 ha = HADATA(gdth_ctr_tab[ldrv.ionode]);
4956 for (i = 0; i < ldrv.drive_cnt && i < MAX_HDRIVES; ++i) {
4958 if (j >= MAX_HDRIVES || !ha->hdr[j].present)
4961 GDTH_LOCK_HA(ha, flags);
4962 ha->hdr[j].lock = 1;
4963 GDTH_UNLOCK_HA(ha, flags);
4964 gdth_wait_completion(ldrv.ionode, ha->bus_cnt, j);
4965 gdth_stop_timeout(ldrv.ionode, ha->bus_cnt, j);
4967 GDTH_LOCK_HA(ha, flags);
4968 ha->hdr[j].lock = 0;
4969 GDTH_UNLOCK_HA(ha, flags);
4970 gdth_start_timeout(ldrv.ionode, ha->bus_cnt, j);
4971 gdth_next(ldrv.ionode);
4977 static int ioc_resetdrv(unsigned long arg, char *cmnd)
4979 gdth_ioctl_reset res;
4983 #if LINUX_VERSION_CODE >= 0x020503
4986 #elif LINUX_VERSION_CODE >= 0x020322
4994 if (copy_from_user(&res, (char *)arg, sizeof(gdth_ioctl_reset)) ||
4995 res.ionode >= gdth_ctr_count || res.number >= MAX_HDRIVES)
4998 ha = HADATA(gdth_ctr_tab[hanum]);
5000 if (!ha->hdr[res.number].present)
5002 cmd.Service = CACHESERVICE;
5003 cmd.OpCode = GDT_CLUST_RESET;
5004 cmd.u.cache.DeviceNo = res.number;
5005 #if LINUX_VERSION_CODE >= 0x020503
5006 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
5007 srp = scsi_allocate_request(sdev, GFP_KERNEL);
5010 srp->sr_cmd_len = 12;
5012 gdth_do_req(srp, &cmd, cmnd, 30);
5013 res.status = (ushort)srp->sr_command->SCp.Status;
5014 scsi_release_request(srp);
5015 scsi_free_host_dev(sdev);
5016 #elif LINUX_VERSION_CODE >= 0x020322
5017 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
5018 scp = scsi_allocate_device(sdev, 1, FALSE);
5023 gdth_do_cmd(scp, &cmd, cmnd, 30);
5024 res.status = (ushort)scp->SCp.Status;
5025 scsi_release_command(scp);
5026 scsi_free_host_dev(sdev);
5028 memset(&sdev,0,sizeof(Scsi_Device));
5029 memset(&scp, 0,sizeof(Scsi_Cmnd));
5030 sdev.host = scp.host = gdth_ctr_tab[hanum];
5031 sdev.id = scp.target = sdev.host->this_id;
5033 gdth_do_cmd(&scp, &cmd, cmnd, 30);
5034 res.status = (ushort)scp.SCp.Status;
5036 if (copy_to_user((char *)arg, &res, sizeof(gdth_ioctl_reset)))
5041 static int ioc_general(unsigned long arg, char *cmnd)
5043 gdth_ioctl_general gen;
5048 #if LINUX_VERSION_CODE >= 0x020503
5051 #elif LINUX_VERSION_CODE >= 0x020322
5059 if (copy_from_user(&gen, (char *)arg, sizeof(gdth_ioctl_general)) ||
5060 gen.ionode >= gdth_ctr_count)
5063 ha = HADATA(gdth_ctr_tab[hanum]);
5064 if (gen.data_len + gen.sense_len != 0) {
5065 if (!(buf = gdth_ioctl_alloc(hanum, gen.data_len + gen.sense_len,
5068 if (copy_from_user(buf, (char *)arg + sizeof(gdth_ioctl_general),
5069 gen.data_len + gen.sense_len)) {
5070 gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
5074 if (gen.command.OpCode == GDT_IOCTL) {
5075 gen.command.u.ioctl.p_param = paddr;
5076 } else if (gen.command.Service == CACHESERVICE) {
5077 if (ha->cache_feat & SCATTER_GATHER) {
5078 gen.command.u.cache.DestAddr = 0xffffffff;
5079 gen.command.u.cache.sg_canz = 1;
5080 gen.command.u.cache.sg_lst[0].sg_ptr = paddr;
5081 gen.command.u.cache.sg_lst[0].sg_len = gen.data_len;
5082 gen.command.u.cache.sg_lst[1].sg_len = 0;
5084 gen.command.u.cache.DestAddr = paddr;
5085 gen.command.u.cache.sg_canz = 0;
5087 } else if (gen.command.Service == SCSIRAWSERVICE) {
5088 if (ha->raw_feat & SCATTER_GATHER) {
5089 gen.command.u.raw.sdata = 0xffffffff;
5090 gen.command.u.raw.sg_ranz = 1;
5091 gen.command.u.raw.sg_lst[0].sg_ptr = paddr;
5092 gen.command.u.raw.sg_lst[0].sg_len = gen.data_len;
5093 gen.command.u.raw.sg_lst[1].sg_len = 0;
5095 gen.command.u.raw.sdata = paddr;
5096 gen.command.u.raw.sg_ranz = 0;
5098 gen.command.u.raw.sense_data = paddr + gen.data_len;
5101 gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
5106 #if LINUX_VERSION_CODE >= 0x020503
5107 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
5108 srp = scsi_allocate_request(sdev, GFP_KERNEL);
5111 srp->sr_cmd_len = 12;
5113 gdth_do_req(srp, &gen.command, cmnd, gen.timeout);
5114 gen.status = srp->sr_command->SCp.Status;
5115 gen.info = srp->sr_command->SCp.Message;
5116 scsi_release_request(srp);
5117 scsi_free_host_dev(sdev);
5118 #elif LINUX_VERSION_CODE >= 0x020322
5119 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
5120 scp = scsi_allocate_device(sdev, 1, FALSE);
5125 gdth_do_cmd(scp, &gen.command, cmnd, gen.timeout);
5126 gen.status = scp->SCp.Status;
5127 gen.info = scp->SCp.Message;
5128 scsi_release_command(scp);
5129 scsi_free_host_dev(sdev);
5131 memset(&sdev,0,sizeof(Scsi_Device));
5132 memset(&scp, 0,sizeof(Scsi_Cmnd));
5133 sdev.host = scp.host = gdth_ctr_tab[hanum];
5134 sdev.id = scp.target = sdev.host->this_id;
5136 gdth_do_cmd(&scp, &gen.command, cmnd, gen.timeout);
5137 gen.status = scp.SCp.Status;
5138 gen.info = scp.SCp.Message;
5141 if (copy_to_user((char *)arg + sizeof(gdth_ioctl_general), buf,
5142 gen.data_len + gen.sense_len)) {
5143 gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
5146 if (copy_to_user((char *)arg, &gen,
5147 sizeof(gdth_ioctl_general) - sizeof(gdth_cmd_str))) {
5148 gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
5151 gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
5155 static int ioc_hdrlist(unsigned long arg, char *cmnd)
5157 gdth_ioctl_rescan rsc;
5162 #if LINUX_VERSION_CODE >= 0x020503
5165 #elif LINUX_VERSION_CODE >= 0x020322
5173 if (copy_from_user(&rsc, (char *)arg, sizeof(gdth_ioctl_rescan)) ||
5174 rsc.ionode >= gdth_ctr_count)
5177 ha = HADATA(gdth_ctr_tab[hanum]);
5179 #if LINUX_VERSION_CODE >= 0x020503
5180 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
5181 srp = scsi_allocate_request(sdev, GFP_KERNEL);
5184 srp->sr_cmd_len = 12;
5186 #elif LINUX_VERSION_CODE >= 0x020322
5187 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
5188 scp = scsi_allocate_device(sdev, 1, FALSE);
5194 memset(&sdev,0,sizeof(Scsi_Device));
5195 memset(&scp, 0,sizeof(Scsi_Cmnd));
5196 sdev.host = scp.host = gdth_ctr_tab[hanum];
5197 sdev.id = scp.target = sdev.host->this_id;
5201 for (i = 0; i < MAX_HDRIVES; ++i) {
5202 if (!ha->hdr[i].present) {
5203 rsc.hdr_list[i].bus = 0xff;
5206 rsc.hdr_list[i].bus = ha->virt_bus;
5207 rsc.hdr_list[i].target = i;
5208 rsc.hdr_list[i].lun = 0;
5209 rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
5210 if (ha->hdr[i].cluster_type & CLUSTER_DRIVE) {
5211 cmd.Service = CACHESERVICE;
5212 cmd.OpCode = GDT_CLUST_INFO;
5213 cmd.u.cache.DeviceNo = i;
5214 #if LINUX_VERSION_CODE >= 0x020503
5215 gdth_do_req(srp, &cmd, cmnd, 30);
5216 if (srp->sr_command->SCp.Status == S_OK)
5217 rsc.hdr_list[i].cluster_type = srp->sr_command->SCp.Message;
5218 #elif LINUX_VERSION_CODE >= 0x020322
5219 gdth_do_cmd(scp, &cmd, cmnd, 30);
5220 if (scp->SCp.Status == S_OK)
5221 rsc.hdr_list[i].cluster_type = scp->SCp.Message;
5223 gdth_do_cmd(&scp, &cmd, cmnd, 30);
5224 if (scp.SCp.Status == S_OK)
5225 rsc.hdr_list[i].cluster_type = scp.SCp.Message;
5229 #if LINUX_VERSION_CODE >= 0x020503
5230 scsi_release_request(srp);
5231 scsi_free_host_dev(sdev);
5232 #elif LINUX_VERSION_CODE >= 0x020322
5233 scsi_release_command(scp);
5234 scsi_free_host_dev(sdev);
5237 if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan)))
5242 static int ioc_rescan(unsigned long arg, char *cmnd)
5244 gdth_ioctl_rescan rsc;
5246 ushort i, status, hdr_cnt;
5248 int hanum, cyls, hds, secs;
5251 #if LINUX_VERSION_CODE >= 0x020503
5254 #elif LINUX_VERSION_CODE >= 0x020322
5262 if (copy_from_user(&rsc, (char *)arg, sizeof(gdth_ioctl_rescan)) ||
5263 rsc.ionode >= gdth_ctr_count)
5266 ha = HADATA(gdth_ctr_tab[hanum]);
5268 #if LINUX_VERSION_CODE >= 0x020503
5269 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
5270 srp = scsi_allocate_request(sdev, GFP_KERNEL);
5273 srp->sr_cmd_len = 12;
5275 #elif LINUX_VERSION_CODE >= 0x020322
5276 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
5277 scp = scsi_allocate_device(sdev, 1, FALSE);
5283 memset(&sdev,0,sizeof(Scsi_Device));
5284 memset(&scp, 0,sizeof(Scsi_Cmnd));
5285 sdev.host = scp.host = gdth_ctr_tab[hanum];
5286 sdev.id = scp.target = sdev.host->this_id;
5290 if (rsc.flag == 0) {
5291 /* old method: re-init. cache service */
5292 cmd.Service = CACHESERVICE;
5293 cmd.OpCode = GDT_INIT;
5294 cmd.u.cache.DeviceNo = LINUX_OS;
5295 #if LINUX_VERSION_CODE >= 0x020503
5296 gdth_do_req(srp, &cmd, cmnd, 30);
5297 status = (ushort)srp->sr_command->SCp.Status;
5298 info = (ulong32)srp->sr_command->SCp.Message;
5299 #elif LINUX_VERSION_CODE >= 0x020322
5300 gdth_do_cmd(scp, &cmd, cmnd, 30);
5301 status = (ushort)scp->SCp.Status;
5302 info = (ulong32)scp->SCp.Message;
5304 gdth_do_cmd(&scp, &cmd, cmnd, 30);
5305 status = (ushort)scp.SCp.Status;
5306 info = (ulong32)scp.SCp.Message;
5309 hdr_cnt = (status == S_OK ? (ushort)info : 0);
5314 for (; i < hdr_cnt && i < MAX_HDRIVES; ++i) {
5315 cmd.Service = CACHESERVICE;
5316 cmd.OpCode = GDT_INFO;
5317 cmd.u.cache.DeviceNo = i;
5318 #if LINUX_VERSION_CODE >= 0x020503
5319 gdth_do_req(srp, &cmd, cmnd, 30);
5320 status = (ushort)srp->sr_command->SCp.Status;
5321 info = (ulong32)srp->sr_command->SCp.Message;
5322 #elif LINUX_VERSION_CODE >= 0x020322
5323 gdth_do_cmd(scp, &cmd, cmnd, 30);
5324 status = (ushort)scp->SCp.Status;
5325 info = (ulong32)scp->SCp.Message;
5327 gdth_do_cmd(&scp, &cmd, cmnd, 30);
5328 status = (ushort)scp.SCp.Status;
5329 info = (ulong32)scp.SCp.Message;
5331 GDTH_LOCK_HA(ha, flags);
5332 rsc.hdr_list[i].bus = ha->virt_bus;
5333 rsc.hdr_list[i].target = i;
5334 rsc.hdr_list[i].lun = 0;
5335 if (status != S_OK) {
5336 ha->hdr[i].present = FALSE;
5338 ha->hdr[i].present = TRUE;
5339 ha->hdr[i].size = info;
5340 /* evaluate mapping */
5341 ha->hdr[i].size &= ~SECS32;
5342 gdth_eval_mapping(ha->hdr[i].size,&cyls,&hds,&secs);
5343 ha->hdr[i].heads = hds;
5344 ha->hdr[i].secs = secs;
5346 ha->hdr[i].size = cyls * hds * secs;
5348 GDTH_UNLOCK_HA(ha, flags);
5352 /* devtype, cluster info, R/W attribs */
5353 cmd.Service = CACHESERVICE;
5354 cmd.OpCode = GDT_DEVTYPE;
5355 cmd.u.cache.DeviceNo = i;
5356 #if LINUX_VERSION_CODE >= 0x020503
5357 gdth_do_req(srp, &cmd, cmnd, 30);
5358 status = (ushort)srp->sr_command->SCp.Status;
5359 info = (ulong32)srp->sr_command->SCp.Message;
5360 #elif LINUX_VERSION_CODE >= 0x020322
5361 gdth_do_cmd(scp, &cmd, cmnd, 30);
5362 status = (ushort)scp->SCp.Status;
5363 info = (ulong32)scp->SCp.Message;
5365 gdth_do_cmd(&scp, &cmd, cmnd, 30);
5366 status = (ushort)scp.SCp.Status;
5367 info = (ulong32)scp.SCp.Message;
5369 GDTH_LOCK_HA(ha, flags);
5370 ha->hdr[i].devtype = (status == S_OK ? (ushort)info : 0);
5371 GDTH_UNLOCK_HA(ha, flags);
5373 cmd.Service = CACHESERVICE;
5374 cmd.OpCode = GDT_CLUST_INFO;
5375 cmd.u.cache.DeviceNo = i;
5376 #if LINUX_VERSION_CODE >= 0x020503
5377 gdth_do_req(srp, &cmd, cmnd, 30);
5378 status = (ushort)srp->sr_command->SCp.Status;
5379 info = (ulong32)srp->sr_command->SCp.Message;
5380 #elif LINUX_VERSION_CODE >= 0x020322
5381 gdth_do_cmd(scp, &cmd, cmnd, 30);
5382 status = (ushort)scp->SCp.Status;
5383 info = (ulong32)scp->SCp.Message;
5385 gdth_do_cmd(&scp, &cmd, cmnd, 30);
5386 status = (ushort)scp.SCp.Status;
5387 info = (ulong32)scp.SCp.Message;
5389 GDTH_LOCK_HA(ha, flags);
5390 ha->hdr[i].cluster_type =
5391 ((status == S_OK && !shared_access) ? (ushort)info : 0);
5392 GDTH_UNLOCK_HA(ha, flags);
5393 rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
5395 cmd.Service = CACHESERVICE;
5396 cmd.OpCode = GDT_RW_ATTRIBS;
5397 cmd.u.cache.DeviceNo = i;
5398 #if LINUX_VERSION_CODE >= 0x020503
5399 gdth_do_req(srp, &cmd, cmnd, 30);
5400 status = (ushort)srp->sr_command->SCp.Status;
5401 info = (ulong32)srp->sr_command->SCp.Message;
5402 #elif LINUX_VERSION_CODE >= 0x020322
5403 gdth_do_cmd(scp, &cmd, cmnd, 30);
5404 status = (ushort)scp->SCp.Status;
5405 info = (ulong32)scp->SCp.Message;
5407 gdth_do_cmd(&scp, &cmd, cmnd, 30);
5408 status = (ushort)scp.SCp.Status;
5409 info = (ulong32)scp.SCp.Message;
5411 GDTH_LOCK_HA(ha, flags);
5412 ha->hdr[i].rw_attribs = (status == S_OK ? (ushort)info : 0);
5413 GDTH_UNLOCK_HA(ha, flags);
5415 #if LINUX_VERSION_CODE >= 0x020503
5416 scsi_release_request(srp);
5417 scsi_free_host_dev(sdev);
5418 #elif LINUX_VERSION_CODE >= 0x020322
5419 scsi_release_command(scp);
5420 scsi_free_host_dev(sdev);
5423 if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan)))
5428 static int gdth_ioctl(struct inode *inode, struct file *filep,
5429 unsigned int cmd, unsigned long arg)
5432 #if LINUX_VERSION_CODE >= 0x020503
5435 #elif LINUX_VERSION_CODE >= 0x020322
5443 char cmnd[MAX_COMMAND_SIZE];
5445 memset(cmnd, 0xff, 12);
5447 TRACE(("gdth_ioctl() cmd 0x%x\n", cmd));
5450 case GDTIOCTL_CTRCNT:
5452 int cnt = gdth_ctr_count;
5453 if (put_user(cnt, (int *)arg))
5458 case GDTIOCTL_DRVERS:
5460 int ver = (GDTH_VERSION<<8) | GDTH_SUBVERSION;
5461 if (put_user(ver, (int *)arg))
5466 case GDTIOCTL_OSVERS:
5468 gdth_ioctl_osvers osv;
5470 osv.version = (unchar)(LINUX_VERSION_CODE >> 16);
5471 osv.subversion = (unchar)(LINUX_VERSION_CODE >> 8);
5472 osv.revision = (ushort)(LINUX_VERSION_CODE & 0xff);
5473 if (copy_to_user((char *)arg, &osv, sizeof(gdth_ioctl_osvers)))
5478 case GDTIOCTL_CTRTYPE:
5480 gdth_ioctl_ctrtype ctrt;
5482 if (copy_from_user(&ctrt, (char *)arg, sizeof(gdth_ioctl_ctrtype)) ||
5483 ctrt.ionode >= gdth_ctr_count)
5485 ha = HADATA(gdth_ctr_tab[ctrt.ionode]);
5486 if (ha->type == GDT_ISA || ha->type == GDT_EISA) {
5487 ctrt.type = (unchar)((ha->stype>>20) - 0x10);
5489 if (ha->type != GDT_PCIMPR) {
5490 ctrt.type = (unchar)((ha->stype<<4) + 6);
5493 (ha->oem_id == OEM_ID_INTEL ? 0xfd : 0xfe);
5494 if (ha->stype >= 0x300)
5495 ctrt.ext_type = 0x6000 | ha->subdevice_id;
5497 ctrt.ext_type = 0x6000 | ha->stype;
5499 ctrt.device_id = ha->stype;
5500 ctrt.sub_device_id = ha->subdevice_id;
5502 ctrt.info = ha->brd_phys;
5503 ctrt.oem_id = ha->oem_id;
5504 if (copy_to_user((char *)arg, &ctrt, sizeof(gdth_ioctl_ctrtype)))
5509 case GDTIOCTL_GENERAL:
5510 return ioc_general(arg, cmnd);
5512 case GDTIOCTL_EVENT:
5513 return ioc_event(arg);
5515 case GDTIOCTL_LOCKDRV:
5516 return ioc_lockdrv(arg);
5518 case GDTIOCTL_LOCKCHN:
5520 gdth_ioctl_lockchn lchn;
5523 if (copy_from_user(&lchn, (char *)arg, sizeof(gdth_ioctl_lockchn)) ||
5524 lchn.ionode >= gdth_ctr_count)
5526 ha = HADATA(gdth_ctr_tab[lchn.ionode]);
5529 if (i < ha->bus_cnt) {
5531 GDTH_LOCK_HA(ha, flags);
5532 ha->raw[i].lock = 1;
5533 GDTH_UNLOCK_HA(ha, flags);
5534 for (j = 0; j < ha->tid_cnt; ++j) {
5535 gdth_wait_completion(lchn.ionode, i, j);
5536 gdth_stop_timeout(lchn.ionode, i, j);
5539 GDTH_LOCK_HA(ha, flags);
5540 ha->raw[i].lock = 0;
5541 GDTH_UNLOCK_HA(ha, flags);
5542 for (j = 0; j < ha->tid_cnt; ++j) {
5543 gdth_start_timeout(lchn.ionode, i, j);
5544 gdth_next(lchn.ionode);
5551 case GDTIOCTL_RESCAN:
5552 return ioc_rescan(arg, cmnd);
5554 case GDTIOCTL_HDRLIST:
5555 return ioc_hdrlist(arg, cmnd);
5557 case GDTIOCTL_RESET_BUS:
5559 gdth_ioctl_reset res;
5562 if (copy_from_user(&res, (char *)arg, sizeof(gdth_ioctl_reset)) ||
5563 res.ionode >= gdth_ctr_count)
5567 /* Because we need a Scsi_Cmnd struct., we make a scsi_allocate device also for kernels >=2.5.x */
5568 #if LINUX_VERSION_CODE >= 0x02053C
5569 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
5570 scp = scsi_get_command(sdev, GFP_KERNEL);
5575 scp->device->channel = virt_ctr ? 0 : res.number;
5576 rval = gdth_eh_bus_reset(scp);
5577 res.status = (rval == SUCCESS ? S_OK : S_GENERR);
5578 scsi_put_command(scp);
5579 scsi_free_host_dev(sdev);
5580 #elif LINUX_VERSION_CODE >= 0x020322
5581 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
5582 #if LINUX_VERSION_CODE >= 0x020503
5583 scp = scsi_allocate_device(sdev, 1);
5585 scp = scsi_allocate_device(sdev, 1, FALSE);
5591 scp->channel = virt_ctr ? 0 : res.number;
5592 rval = gdth_eh_bus_reset(scp);
5593 res.status = (rval == SUCCESS ? S_OK : S_GENERR);
5594 scsi_release_command(scp);
5595 scsi_free_host_dev(sdev);
5596 #elif LINUX_VERSION_CODE >= 0x02015F
5597 memset(&sdev,0,sizeof(Scsi_Device));
5598 memset(&scp, 0,sizeof(Scsi_Cmnd));
5599 sdev.host = scp.host = gdth_ctr_tab[hanum];
5600 sdev.id = scp.target = sdev.host->this_id;
5602 scp.channel = virt_ctr ? 0 : res.number;
5603 rval = gdth_eh_bus_reset(&scp);
5604 res.status = (rval == SUCCESS ? S_OK : S_GENERR);
5608 if (copy_to_user((char *)arg, &res, sizeof(gdth_ioctl_reset)))
5613 case GDTIOCTL_RESET_DRV:
5614 return ioc_resetdrv(arg, cmnd);
5623 #if LINUX_VERSION_CODE >= 0x010300
5625 static void gdth_flush(int hanum)
5629 gdth_cmd_str gdtcmd;
5630 #if LINUX_VERSION_CODE >= 0x020503
5633 #elif LINUX_VERSION_CODE >= 0x020322
5640 char cmnd[MAX_COMMAND_SIZE];
5641 memset(cmnd, 0xff, MAX_COMMAND_SIZE);
5643 TRACE2(("gdth_flush() hanum %d\n",hanum));
5644 ha = HADATA(gdth_ctr_tab[hanum]);
5646 #if LINUX_VERSION_CODE >= 0x020503
5647 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
5648 srp = scsi_allocate_request(sdev, GFP_KERNEL);
5651 srp->sr_cmd_len = 12;
5653 #elif LINUX_VERSION_CODE >= 0x020322
5654 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
5655 scp = scsi_allocate_device(sdev, 1, FALSE);
5661 memset(&sdev,0,sizeof(Scsi_Device));
5662 memset(&scp, 0,sizeof(Scsi_Cmnd));
5663 sdev.host = scp.host = gdth_ctr_tab[hanum];
5664 sdev.id = scp.target = sdev.host->this_id;
5668 for (i = 0; i < MAX_HDRIVES; ++i) {
5669 if (ha->hdr[i].present) {
5670 gdtcmd.BoardNode = LOCALBOARD;
5671 gdtcmd.Service = CACHESERVICE;
5672 gdtcmd.OpCode = GDT_FLUSH;
5673 gdtcmd.u.cache.DeviceNo = i;
5674 gdtcmd.u.cache.BlockNo = 1;
5675 gdtcmd.u.cache.sg_canz = 0;
5676 TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i));
5677 #if LINUX_VERSION_CODE >= 0x020503
5678 gdth_do_req(srp, &gdtcmd, cmnd, 30);
5679 #elif LINUX_VERSION_CODE >= 0x020322
5680 gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
5682 gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
5686 #if LINUX_VERSION_CODE >= 0x020503
5687 scsi_release_request(srp);
5688 scsi_free_host_dev(sdev);
5689 #elif LINUX_VERSION_CODE >= 0x020322
5690 scsi_release_command(scp);
5691 scsi_free_host_dev(sdev);
5695 /* shutdown routine */
5696 #if LINUX_VERSION_CODE >= 0x020100
5697 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
5699 void gdth_halt(void)
5704 gdth_cmd_str gdtcmd;
5705 #if LINUX_VERSION_CODE >= 0x020503
5708 #elif LINUX_VERSION_CODE >= 0x020322
5715 char cmnd[MAX_COMMAND_SIZE];
5718 #if LINUX_VERSION_CODE >= 0x020100
5719 TRACE2(("gdth_halt() event %d\n",(int)event));
5720 if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
5723 TRACE2(("gdth_halt()\n"));
5725 TRACE2(("already called\n"));
5731 printk("GDT: Flushing all host drives .. ");
5732 for (hanum = 0; hanum < gdth_ctr_count; ++hanum) {
5736 /* controller reset */
5737 memset(cmnd, 0xff, MAX_COMMAND_SIZE);
5738 gdtcmd.BoardNode = LOCALBOARD;
5739 gdtcmd.Service = CACHESERVICE;
5740 gdtcmd.OpCode = GDT_RESET;
5741 TRACE2(("gdth_halt(): reset controller %d\n", hanum));
5742 #if LINUX_VERSION_CODE >= 0x020503
5743 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
5744 srp = scsi_allocate_request(sdev, GFP_KERNEL);
5746 #if LINUX_VERSION_CODE >= 0x020100
5747 unregister_reboot_notifier(&gdth_notifier);
5753 srp->sr_cmd_len = 12;
5755 gdth_do_req(srp, &gdtcmd, cmnd, 10);
5756 scsi_release_request(srp);
5757 scsi_free_host_dev(sdev);
5758 #elif LINUX_VERSION_CODE >= 0x020322
5759 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
5760 scp = scsi_allocate_device(sdev, 1, FALSE);
5762 #if LINUX_VERSION_CODE >= 0x020100
5763 unregister_reboot_notifier(&gdth_notifier);
5771 gdth_do_cmd(scp, &gdtcmd, cmnd, 10);
5772 scsi_release_command(scp);
5773 scsi_free_host_dev(sdev);
5775 memset(&sdev,0,sizeof(Scsi_Device));
5776 memset(&scp, 0,sizeof(Scsi_Cmnd));
5777 sdev.host = scp.host = gdth_ctr_tab[hanum];
5778 sdev.id = scp.target = sdev.host->this_id;
5780 gdth_do_cmd(&scp, &gdtcmd, cmnd, 10);
5786 #ifdef GDTH_STATISTICS
5787 del_timer(&gdth_timer);
5789 #if LINUX_VERSION_CODE >= 0x020100
5790 unregister_reboot_notifier(&gdth_notifier);
5797 #if LINUX_VERSION_CODE < 0x020400 && !defined(MODULE)
5799 GDTH_INITFUNC(void, gdth_setup(char *str,int *ints))
5801 TRACE2(("gdth_setup() str %s ints[0] %d\n",
5802 str ? str:"NULL", ints ? ints[0]:0));
5803 internal_setup(str, ints);
5808 static Scsi_Host_Template driver_template = {
5809 #if LINUX_VERSION_CODE >= 0x02015F
5810 .proc_name = "gdth",
5812 .proc_dir = &proc_scsi_gdth,
5814 .proc_info = gdth_proc_info,
5815 .name = "GDT SCSI Disk Array Controller",
5816 .detect = gdth_detect,
5817 .release = gdth_release,
5819 .queuecommand = gdth_queuecommand,
5820 .eh_abort_handler = gdth_eh_abort,
5821 .eh_device_reset_handler = gdth_eh_device_reset,
5822 .eh_bus_reset_handler = gdth_eh_bus_reset,
5823 .eh_host_reset_handler = gdth_eh_host_reset,
5824 .bios_param = gdth_bios_param,
5825 .can_queue = GDTH_MAXCMDS,
5827 .sg_tablesize = GDTH_MAXSG,
5828 .cmd_per_lun = GDTH_MAXC_P_L,
5829 .unchecked_isa_dma = 1,
5830 .use_clustering = ENABLE_CLUSTERING,
5831 #if LINUX_VERSION_CODE < 0x020501
5832 .use_new_eh_code = 1,
5836 #include "scsi_module.c"
5838 __setup("gdth=", option_setup);