1 /************************************************************************
2 * GDT ISA/EISA/PCI Disk Array Controller driver for Linux *
5 * Copyright (C) 1995-99 ICP vortex Computersysteme GmbH, Achim Leubner *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published *
11 * by the Free Software Foundation; either version 2 of the License, *
12 * or (at your option) any later version. *
14 * This program is distributed in the hope that it will be useful, *
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17 * GNU General Public License for more details. *
19 * You should have received a copy of the GNU General Public License *
20 * along with this kernel; if not, write to the Free Software *
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
23 * Tested with Linux 1.2.13, ..., 2.2.4 *
26 * Revision 1.23 1999/03/26 09:12:31 achim
27 * Default value for hdr_channel set to 0
29 * Revision 1.22 1999/03/22 16:27:16 achim
30 * Bugfix: gdth_store_event() must not be locked with GDTH_LOCK_HA()
32 * Revision 1.21 1999/03/16 13:40:34 achim
33 * Problems with reserved drives solved
34 * gdth_eh_bus_reset() implemented
36 * Revision 1.20 1999/03/10 09:08:13 achim
37 * Bugfix: Corrections in gdth_direction_tab[] made
38 * Bugfix: Increase command timeout (gdth_update_timeout()) NOT in gdth_putq()
40 * Revision 1.19 1999/03/05 14:38:16 achim
41 * Bugfix: Heads/Sectors mapping for reserved devices possibly wrong
42 * -> gdth_eval_mapping() implemented, changes in gdth_bios_param()
43 * INIT_RETRIES set to 100s to avoid DEINIT-Timeout for controllers
44 * with BIOS disabled and memory test set to Intensive
45 * Enhanced /proc support
47 * Revision 1.18 1999/02/24 09:54:33 achim
48 * Command line parameter hdr_channel implemented
49 * Bugfix for EISA controllers + Linux 2.2.x
51 * Revision 1.17 1998/12/17 15:58:11 achim
52 * Command line parameters implemented
53 * Changes for Alpha platforms
54 * PCI controller scan changed
55 * SMP support improved (spin_lock_irqsave(),...)
56 * New async. events, new scan/reserve commands included
58 * Revision 1.16 1998/09/28 16:08:46 achim
59 * GDT_PCIMPR: DPMEM remapping, if required
62 * Revision 1.15 1998/06/03 14:54:06 achim
63 * gdth_delay(), gdth_flush() implemented
64 * Bugfix: gdth_release() changed
66 * Revision 1.14 1998/05/22 10:01:17 achim
67 * mj: pcibios_strerror() removed
68 * Improved SMP support (if version >= 2.1.95)
69 * gdth_halt(): halt_called flag added (if version < 2.1)
71 * Revision 1.13 1998/04/16 09:14:57 achim
72 * Reserve drives (for raw service) implemented
73 * New error handling code enabled
74 * Get controller name from board_info() IOCTL
75 * Final round of PCI device driver patches by Martin Mares
77 * Revision 1.12 1998/03/03 09:32:37 achim
78 * Fibre channel controller support added
80 * Revision 1.11 1998/01/27 16:19:14 achim
82 * add_timer()/del_timer() instead of GDTH_TIMER
83 * scsi_add_timer()/scsi_del_timer() instead of SCSI_TIMER
84 * New error handling included
86 * Revision 1.10 1997/10/31 12:29:57 achim
87 * Read heads/sectors from host drive
89 * Revision 1.9 1997/09/04 10:07:25 achim
90 * IO-mapping with virt_to_bus(), gdth_readb(), gdth_writeb(), ...
91 * register_reboot_notifier() to get a notify on shutdown used
93 * Revision 1.8 1997/04/02 12:14:30 achim
94 * Version 1.00 (see gdth.h), tested with kernel 2.0.29
96 * Revision 1.7 1997/03/12 13:33:37 achim
97 * gdth_reset() changed, new async. events
99 * Revision 1.6 1997/03/04 14:01:11 achim
100 * Shutdown routine gdth_halt() implemented
102 * Revision 1.5 1997/02/21 09:08:36 achim
103 * New controller included (RP, RP1, RP2 series)
104 * IOCTL interface implemented
106 * Revision 1.4 1996/07/05 12:48:55 achim
107 * Function gdth_bios_param() implemented
108 * New constant GDTH_MAXC_P_L inserted
109 * GDT_WRITE_THR, GDT_EXT_INFO implemented
110 * Function gdth_reset() changed
112 * Revision 1.3 1996/05/10 09:04:41 achim
113 * Small changes for Linux 1.2.13
115 * Revision 1.2 1996/05/09 12:45:27 achim
116 * Loadable module support implemented
117 * /proc support corrections made
119 * Revision 1.1 1996/04/11 07:35:57 achim
122 ************************************************************************/
123 #ident "$Id: gdth.c,v 1.23 1999/03/26 09:12:31 achim Exp $"
125 /* All GDT Disk Array Controllers are fully supported by this driver.
126 * This includes the PCI/EISA/ISA SCSI Disk Array Controllers and the
127 * PCI Fibre Channel Disk Array Controllers. See gdth.h for a complete
128 * list of all controller types.
130 * If you have one or more GDT3000/3020 EISA controllers with
131 * controller BIOS disabled, you have to set the IRQ values with the
132 * command line option "gdth=irq1,irq2,...", where the irq1,irq2,... are
133 * the IRQ values for the EISA controllers.
135 * After the optional list of IRQ values, other possible
136 * command line options are:
137 * disable:Y disable driver
138 * disable:N enable driver
139 * reserve_mode:0 reserve no drives for the raw service
140 * reserve_mode:1 reserve all not init., removable drives
141 * reserve_mode:2 reserve all not init. drives
142 * reserve_list:h,b,t,l,h,b,t,l,... reserve particular drive(s) with
143 * h- controller no., b- channel no.,
144 * t- target ID, l- LUN
145 * reverse_scan:Y reverse scan order for PCI controllers
146 * reverse_scan:N scan PCI controllers like BIOS
147 * max_ids:x x - target ID count per channel (1..MAXID)
148 * rescan:Y rescan all channels/IDs
149 * rescan:N use all devices found until now
150 * hdr_channel:x x - number of virtual bus for host drives
152 * The default value is: "gdth=disable:N,reserve_mode:1,reverse_scan:N,
153 * max_ids:127,rescan:N,hdr_channel:0".
154 * Here is another example: "gdth=reserve_list:0,1,2,0,0,1,3,0,rescan:Y".
156 * When loading the gdth driver as a module, the same options are available.
157 * You can set the IRQs with "IRQ=...". However, the syntax to specify the
158 * options changes slightly. You must replace all ',' between options
159 * with ' ' and all ':' with '=' and you must use
160 * '1' in place of 'Y' and '0' in place of 'N'.
162 * Default: "modprobe gdth disable=0 reserve_mode=1 reverse_scan=0
163 * max_ids=127 rescan=0 hdr_channel=0"
164 * The other example: "modprobe gdth reserve_list=0,1,2,0,0,1,3,0 rescan=1".
168 #include <linux/module.h>
171 #include <linux/version.h>
172 #include <linux/kernel.h>
173 #include <linux/types.h>
174 #include <linux/pci.h>
175 #include <linux/string.h>
176 #include <linux/ctype.h>
177 #include <linux/ioport.h>
178 #include <linux/delay.h>
179 #include <linux/sched.h>
180 #include <linux/in.h>
181 #include <linux/proc_fs.h>
182 #include <linux/time.h>
183 #include <linux/timer.h>
184 #if LINUX_VERSION_CODE >= 0x020100
185 #include <linux/reboot.h>
187 #include <linux/bios32.h>
191 #include <asm/system.h>
193 #if LINUX_VERSION_CODE >= 0x02015F
194 #include <linux/spinlock.h>
197 #if LINUX_VERSION_CODE >= 0x010300
198 #include <linux/blk.h>
200 #include "../block/blk.h"
208 static void gdth_delay(int milliseconds
);
209 static void gdth_eval_mapping(ulong32 size
, int *cyls
, int *heads
, int *secs
);
210 #if LINUX_VERSION_CODE >= 0x010346
211 static void gdth_interrupt(int irq
,void *dev_id
,struct pt_regs
*regs
);
213 static void gdth_interrupt(int irq
,struct pt_regs
*regs
);
215 static int gdth_sync_event(int hanum
,int service
,unchar index
,Scsi_Cmnd
*scp
);
216 static int gdth_async_event(int hanum
,int service
);
217 static void gdth_log_event(gdth_evt_data
*dvr
, char *buffer
);
219 static void gdth_putq(int hanum
,Scsi_Cmnd
*scp
,unchar priority
);
220 static void gdth_next(int hanum
);
221 static int gdth_fill_raw_cmd(int hanum
,Scsi_Cmnd
*scp
,unchar b
);
222 static int gdth_special_cmd(int hanum
,Scsi_Cmnd
*scp
);
223 static gdth_evt_str
*gdth_store_event(gdth_ha_str
*ha
, ushort source
,
224 ushort idx
, gdth_evt_data
*evt
);
225 static int gdth_read_event(gdth_ha_str
*ha
, int handle
, gdth_evt_str
*estr
);
226 static void gdth_readapp_event(gdth_ha_str
*ha
, unchar application
,
228 static void gdth_clear_events(void);
230 static void gdth_copy_internal_data(Scsi_Cmnd
*scp
,char *buffer
,ushort count
);
231 static int gdth_internal_cache_cmd(int hanum
,Scsi_Cmnd
*scp
);
232 static int gdth_fill_cache_cmd(int hanum
,Scsi_Cmnd
*scp
,ushort hdrive
);
234 static int gdth_search_eisa(ushort eisa_adr
);
235 static int gdth_search_isa(ulong32 bios_adr
);
236 static int gdth_search_pci(gdth_pci_str
*pcistr
);
237 static void gdth_sort_pci(gdth_pci_str
*pcistr
, int cnt
);
238 static int gdth_init_eisa(ushort eisa_adr
,gdth_ha_str
*ha
);
239 static int gdth_init_isa(ulong32 bios_adr
,gdth_ha_str
*ha
);
240 static int gdth_init_pci(gdth_pci_str
*pcistr
,gdth_ha_str
*ha
);
242 static void gdth_enable_int(int hanum
);
243 static int gdth_get_status(unchar
*pIStatus
,int irq
);
244 static int gdth_test_busy(int hanum
);
245 static int gdth_get_cmd_index(int hanum
);
246 static void gdth_release_event(int hanum
);
247 static int gdth_wait(int hanum
,int index
,ulong32 time
);
248 static int gdth_internal_cmd(int hanum
,unchar service
,ushort opcode
,ulong32 p1
,
249 ulong32 p2
,ulong32 p3
);
250 static int gdth_search_drives(int hanum
);
252 static void *gdth_mmap(ulong paddr
, ulong size
);
253 static void gdth_munmap(void *addr
);
255 static const char *gdth_ctr_name(int hanum
);
257 #if LINUX_VERSION_CODE >= 0x010300
258 static void gdth_flush(int hanum
);
259 #if LINUX_VERSION_CODE >= 0x020100
260 static int gdth_halt(struct notifier_block
*nb
, ulong event
, void *buf
);
262 static int halt_called
= FALSE
;
263 void gdth_halt(void);
268 static unchar DebugState
= DEBUG_GDTH
;
269 extern long sys_syslog(int,char*,int);
270 #define LOGEN sys_syslog(7,NULL,0)
273 #define MAX_SERBUF 160
274 static void ser_init(void);
275 static void ser_puts(char *str
);
276 static void ser_putc(char c
);
277 static int ser_printk(const char *fmt
, ...);
278 static char strbuf
[MAX_SERBUF
+1];
280 #define COM_BASE 0x2f8
282 #define COM_BASE 0x3f8
284 static void ser_init()
286 unsigned port
=COM_BASE
;
290 /* 19200 Baud, if 9600: outb(12,port) */
300 static void ser_puts(char *str
)
305 for (ptr
=str
;*ptr
;++ptr
)
309 static void ser_putc(char c
)
311 unsigned port
=COM_BASE
;
313 while ((inb(port
+5) & 0x20)==0);
317 while ((inb(port
+5) & 0x20)==0);
322 static int ser_printk(const char *fmt
, ...)
328 i
= vsprintf(strbuf
,fmt
,args
);
334 #define TRACE(a) {if (DebugState==1) {ser_printk a;}}
335 #define TRACE2(a) {if (DebugState==1 || DebugState==2) {ser_printk a;}}
336 #define TRACE3(a) {if (DebugState!=0) {ser_printk a;}}
338 #else /* !__SERIAL__ */
339 #define TRACE(a) {if (DebugState==1) {LOGEN;printk a;}}
340 #define TRACE2(a) {if (DebugState==1 || DebugState==2) {LOGEN;printk a;}}
341 #define TRACE3(a) {if (DebugState!=0) {LOGEN;printk a;}}
350 #ifdef GDTH_STATISTICS
351 static ulong32 max_rq
=0, max_index
=0, max_sg
=0;
352 static ulong32 act_ints
=0, act_ios
=0, act_stats
=0, act_rq
=0;
353 static struct timer_list gdth_timer
;
356 #define PTR2USHORT(a) (ushort)(ulong)(a)
357 #define GDTOFFSOF(a,b) (size_t)&(((a*)0)->b)
358 #define INDEX_OK(i,t) ((i)<sizeof(t)/sizeof((t)[0]))
360 #define NUMDATA(a) ( (gdth_num_str *)((a)->hostdata))
361 #define HADATA(a) (&((gdth_ext_str *)((a)->hostdata))->haext)
362 #define CMDDATA(a) (&((gdth_ext_str *)((a)->hostdata))->cmdext)
364 #define BUS_L2P(a,b) ((b)>(a)->virt_bus ? (b-1):(b))
366 #if LINUX_VERSION_CODE < 0x010300
367 static void *gdth_mmap(ulong paddr
, ulong size
)
369 if (paddr
>= high_memory
)
372 return (void *)paddr
;
374 static void gdth_munmap(void *addr
)
377 inline ulong32
virt_to_phys(volatile void *addr
)
379 return (ulong32
)addr
;
381 inline void *phys_to_virt(ulong32 addr
)
385 #define virt_to_bus virt_to_phys
386 #define bus_to_virt phys_to_virt
387 #define gdth_readb(addr) (*(volatile unchar *)(addr))
388 #define gdth_readw(addr) (*(volatile ushort *)(addr))
389 #define gdth_readl(addr) (*(volatile ulong32 *)(addr))
390 #define gdth_writeb(b,addr) (*(volatile unchar *)(addr) = (b))
391 #define gdth_writew(b,addr) (*(volatile ushort *)(addr) = (b))
392 #define gdth_writel(b,addr) (*(volatile ulong32 *)(addr) = (b))
393 #define memset_io(a,b,c) memset((void *)(a),(b),(c))
394 #define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
395 #define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
397 #define PCI_SLOT(devfn) ((devfn >> 3) & 0x1f)
399 #elif LINUX_VERSION_CODE < 0x020100
400 static int remapped
= FALSE
;
401 static void *gdth_mmap(ulong paddr
, ulong size
)
403 if ( paddr
>= high_memory
) {
405 return vremap(paddr
, size
);
407 return (void *)paddr
;
410 static void gdth_munmap(void *addr
)
416 #define gdth_readb(addr) readb((ulong)(addr))
417 #define gdth_readw(addr) readw((ulong)(addr))
418 #define gdth_readl(addr) (ulong32)readl((ulong)(addr))
419 #define gdth_writeb(b,addr) writeb((b),(ulong)(addr))
420 #define gdth_writew(b,addr) writew((b),(ulong)(addr))
421 #define gdth_writel(b,addr) writel((b),(ulong)(addr))
424 static void *gdth_mmap(ulong paddr
, ulong size
)
426 return ioremap(paddr
, size
);
428 static void gdth_munmap(void *addr
)
430 return iounmap(addr
);
432 #define gdth_readb(addr) readb((ulong)(addr))
433 #define gdth_readw(addr) readw((ulong)(addr))
434 #define gdth_readl(addr) (ulong32)readl((ulong)(addr))
435 #define gdth_writeb(b,addr) writeb((b),(ulong)(addr))
436 #define gdth_writew(b,addr) writew((b),(ulong)(addr))
437 #define gdth_writel(b,addr) writel((b),(ulong)(addr))
441 static unchar gdth_drq_tab
[4] = {5,6,7,7}; /* DRQ table */
442 static unchar gdth_irq_tab
[6] = {0,10,11,12,14,0}; /* IRQ table */
443 static unchar gdth_polling
; /* polling if TRUE */
444 static unchar gdth_from_wait
= FALSE
; /* gdth_wait() */
445 static int wait_index
,wait_hanum
; /* gdth_wait() */
446 static int gdth_ctr_count
= 0; /* controller count */
447 static int gdth_ctr_vcount
= 0; /* virt. ctr. count */
448 static int gdth_ctr_released
= 0; /* gdth_release() */
449 static struct Scsi_Host
*gdth_ctr_tab
[MAXHA
]; /* controller table */
450 static struct Scsi_Host
*gdth_ctr_vtab
[MAXHA
*MAXBUS
]; /* virt. ctr. table */
451 static unchar gdth_write_through
= FALSE
; /* write through */
452 static gdth_evt_str ebuffer
[MAX_EVENTS
]; /* event buffer */
456 #define DIN 1 /* IN data direction */
457 #define DOU 2 /* OUT data direction */
458 #define DNO DIN /* no data transfer */
459 #define DUN DIN /* unknown data direction */
460 static unchar gdth_direction_tab
[0x100] = {
461 DNO
,DNO
,DIN
,DIN
,DOU
,DIN
,DIN
,DOU
,DIN
,DUN
,DOU
,DOU
,DUN
,DUN
,DUN
,DIN
,
462 DNO
,DIN
,DIN
,DOU
,DIN
,DOU
,DNO
,DNO
,DOU
,DNO
,DIN
,DNO
,DIN
,DOU
,DNO
,DUN
,
463 DIN
,DUN
,DIN
,DUN
,DOU
,DIN
,DUN
,DUN
,DIN
,DIN
,DOU
,DNO
,DUN
,DIN
,DOU
,DOU
,
464 DOU
,DOU
,DOU
,DNO
,DIN
,DNO
,DNO
,DIN
,DOU
,DOU
,DOU
,DOU
,DIN
,DOU
,DIN
,DOU
,
465 DOU
,DOU
,DIN
,DIN
,DIN
,DNO
,DUN
,DNO
,DNO
,DNO
,DUN
,DNO
,DOU
,DIN
,DUN
,DUN
,
466 DUN
,DUN
,DUN
,DUN
,DUN
,DOU
,DUN
,DUN
,DUN
,DUN
,DIN
,DUN
,DUN
,DUN
,DUN
,DUN
,
467 DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,
468 DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,
469 DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,
470 DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,
471 DUN
,DUN
,DUN
,DUN
,DUN
,DNO
,DNO
,DUN
,DIN
,DNO
,DOU
,DUN
,DNO
,DUN
,DOU
,DOU
,
472 DOU
,DOU
,DOU
,DNO
,DUN
,DIN
,DOU
,DIN
,DIN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,
473 DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,
474 DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,
475 DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DOU
,DUN
,DUN
,DUN
,DUN
,DUN
,
476 DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
,DUN
479 /* __initfunc, __initdata macros */
480 #if LINUX_VERSION_CODE >= 0x020126
481 #include <linux/init.h>
483 #define __initfunc(A) A
488 #if LINUX_VERSION_CODE >= 0x02015F
489 #define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock)
490 #define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags)
491 #define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags)
493 #define GDTH_LOCK_SCSI_DONE(flags) spin_lock_irqsave(&io_request_lock,flags)
494 #define GDTH_UNLOCK_SCSI_DONE(flags) spin_unlock_irqrestore(&io_request_lock,flags)
495 #define GDTH_LOCK_SCSI_DOCMD() spin_lock_irq(&io_request_lock)
496 #define GDTH_UNLOCK_SCSI_DOCMD() spin_unlock_irq(&io_request_lock)
498 #define GDTH_INIT_LOCK_HA(ha) do {} while (0)
499 #define GDTH_LOCK_HA(ha,flags) do {save_flags(flags); cli();} while (0)
500 #define GDTH_UNLOCK_HA(ha,flags) do {restore_flags(flags);} while (0)
502 #define GDTH_LOCK_SCSI_DONE(flags) do {} while (0)
503 #define GDTH_UNLOCK_SCSI_DONE(flags) do {} while (0)
504 #define GDTH_LOCK_SCSI_DOCMD() do {} while (0)
505 #define GDTH_UNLOCK_SCSI_DOCMD() do {} while (0)
508 /* LILO and modprobe/insmod parameters */
509 /* IRQ list for GDT3000/3020 EISA controllers */
510 static int irq
[MAXHA
] __initdata
=
511 {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
512 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
513 /* disable driver flag */
514 static int disable __initdata
= 0;
516 static int reserve_mode
= 1;
518 static int reserve_list
[MAX_RES_ARGS
] =
519 {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
520 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
521 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
522 /* scan order for PCI controllers */
523 static int reverse_scan
= 0;
524 /* virtual channel for the host drives */
525 static int hdr_channel
= 0;
526 /* max. IDs per channel */
527 static int max_ids
= MAXID
;
529 static int rescan
= 0;
532 #if LINUX_VERSION_CODE >= 0x02011A
533 /* parameters for modprobe/insmod */
534 MODULE_PARM(irq
, "i");
535 MODULE_PARM(disable
, "i");
536 MODULE_PARM(reserve_mode
, "i");
537 MODULE_PARM(reserve_list
, "4-" __MODULE_STRING(MAX_RES_ARGS
) "i");
538 MODULE_PARM(reverse_scan
, "i");
539 MODULE_PARM(hdr_channel
, "i");
540 MODULE_PARM(max_ids
, "i");
541 MODULE_PARM(rescan
, "i");
542 MODULE_AUTHOR("Achim Leubner");
547 #if LINUX_VERSION_CODE >= 0x010300
548 #include <linux/stat.h>
549 struct proc_dir_entry proc_scsi_gdth
= {
550 PROC_SCSI_GDTH
, 4, "gdth",
551 S_IFDIR
| S_IRUGO
| S_IXUGO
, 2
553 #include "gdth_proc.h"
554 #include "gdth_proc.c"
557 #if LINUX_VERSION_CODE >= 0x020100
558 /* notifier block to get a notify on system shutdown/halt/reboot */
559 static struct notifier_block gdth_notifier
= {
565 static void gdth_delay(int milliseconds
)
567 if (milliseconds
== 0) {
570 #if LINUX_VERSION_CODE >= 0x020168
571 mdelay(milliseconds
);
574 for (i
= 0; i
< milliseconds
; ++i
)
580 static void gdth_eval_mapping(ulong32 size
, int *cyls
, int *heads
, int *secs
)
582 *cyls
= size
/HEADS
/SECS
;
583 if (*cyls
<= MAXCYLS
) {
586 } else { /* too high for 64*32 */
587 *cyls
= size
/MEDHEADS
/MEDSECS
;
588 if (*cyls
<= MAXCYLS
) {
591 } else { /* too high for 127*63 */
592 *cyls
= size
/BIGHEADS
/BIGSECS
;
599 /* controller search and initialization functions */
601 static int __init
gdth_search_eisa(ushort eisa_adr
)
605 TRACE(("gdth_search_eisa() adr. %x\n",eisa_adr
));
606 id
= inl(eisa_adr
+ID0REG
);
607 if (id
== GDT3A_ID
|| id
== GDT3B_ID
) { /* GDT3000A or GDT3000B */
608 if ((inb(eisa_adr
+EISAREG
) & 8) == 0)
609 return 0; /* not EISA configured */
612 if (id
== GDT3_ID
) /* GDT3000 */
619 static int __init
gdth_search_isa(ulong32 bios_adr
)
624 TRACE(("gdth_search_isa() bios adr. %x\n",bios_adr
));
625 if ((addr
= gdth_mmap(bios_adr
+BIOS_ID_OFFS
, sizeof(ulong32
))) != NULL
) {
626 id
= gdth_readl(addr
);
628 if (id
== GDT2_ID
) /* GDT2000 */
635 static int __init
gdth_search_pci(gdth_pci_str
*pcistr
)
637 ulong32 base0
, base1
, base2
;
638 ushort device_id
, cnt
;
639 #if LINUX_VERSION_CODE >= 0x2015C
640 struct pci_dev
*pdev
;
646 TRACE(("gdth_search_pci()\n"));
649 for (device_id
= 0; device_id
<= PCI_DEVICE_ID_VORTEX_GDTMAXRP
;
651 if (device_id
> PCI_DEVICE_ID_VORTEX_GDT6555
&&
652 device_id
< PCI_DEVICE_ID_VORTEX_GDT6x17RP
)
655 while ((pdev
= pci_find_device(PCI_VENDOR_ID_VORTEX
,device_id
,pdev
))
659 /* GDT PCI controller found, resources are already in pdev */
660 pcistr
[cnt
].pdev
= pdev
;
661 pcistr
[cnt
].device_id
= device_id
;
662 pcistr
[cnt
].bus
= pdev
->bus
->number
;
663 pcistr
[cnt
].device_fn
= pdev
->devfn
;
664 pcistr
[cnt
].irq
= pdev
->irq
;
665 base0
= pdev
->resource
[0].flags
;
666 base1
= pdev
->resource
[1].flags
;
667 base2
= pdev
->resource
[2].flags
;
668 if (device_id
<= PCI_DEVICE_ID_VORTEX_GDT6000B
|| /* GDT6000/B */
669 device_id
>= PCI_DEVICE_ID_VORTEX_GDT6x17RP
) { /* MPR */
670 if ((base0
& PCI_BASE_ADDRESS_SPACE
) !=
671 PCI_BASE_ADDRESS_SPACE_MEMORY
)
673 pcistr
[cnt
].dpmem
= pdev
->resource
[0].start
;
674 } else { /* GDT6110, GDT6120, .. */
675 if ((base0
& PCI_BASE_ADDRESS_SPACE
) !=
676 PCI_BASE_ADDRESS_SPACE_MEMORY
||
677 (base2
& PCI_BASE_ADDRESS_SPACE
) !=
678 PCI_BASE_ADDRESS_SPACE_MEMORY
||
679 (base1
& PCI_BASE_ADDRESS_SPACE
) !=
680 PCI_BASE_ADDRESS_SPACE_IO
)
682 pcistr
[cnt
].dpmem
= pdev
->resource
[2].start
;
683 pcistr
[cnt
].io_mm
= pdev
->resource
[0].start
;
684 pcistr
[cnt
].io
= pdev
->resource
[1].start
;
686 TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%x\n",
687 pcistr
[cnt
].bus
, PCI_SLOT(pcistr
[cnt
].device_fn
),
688 pcistr
[cnt
].irq
, pcistr
[cnt
].dpmem
));
696 static void __init
gdth_sort_pci(gdth_pci_str
*pcistr
, int cnt
)
701 TRACE(("gdth_sort_pci() cnt %d\n",cnt
));
707 for (i
= 0; i
< cnt
-1; ++i
) {
709 if ((pcistr
[i
].bus
> pcistr
[i
+1].bus
) ||
710 (pcistr
[i
].bus
== pcistr
[i
+1].bus
&&
711 PCI_SLOT(pcistr
[i
].device_fn
) >
712 PCI_SLOT(pcistr
[i
+1].device_fn
))) {
714 pcistr
[i
] = pcistr
[i
+1];
719 if ((pcistr
[i
].bus
< pcistr
[i
+1].bus
) ||
720 (pcistr
[i
].bus
== pcistr
[i
+1].bus
&&
721 PCI_SLOT(pcistr
[i
].device_fn
) <
722 PCI_SLOT(pcistr
[i
+1].device_fn
))) {
724 pcistr
[i
] = pcistr
[i
+1];
734 static int __init
gdth_init_eisa(ushort eisa_adr
,gdth_ha_str
*ha
)
737 unchar prot_ver
,eisacf
,i
,irq_found
;
739 TRACE(("gdth_init_eisa() adr. %x\n",eisa_adr
));
741 /* disable board interrupts, deinitialize services */
742 outb(0xff,eisa_adr
+EDOORREG
);
743 outb(0x00,eisa_adr
+EDENABREG
);
744 outb(0x00,eisa_adr
+EINTENABREG
);
746 outb(0xff,eisa_adr
+LDOORREG
);
747 retries
= INIT_RETRIES
;
749 while (inb(eisa_adr
+EDOORREG
) != 0xff) {
750 if (--retries
== 0) {
751 printk("GDT-EISA: Initialization error (DEINIT failed)\n");
755 TRACE2(("wait for DEINIT: retries=%d\n",retries
));
757 prot_ver
= inb(eisa_adr
+MAILBOXREG
);
758 outb(0xff,eisa_adr
+EDOORREG
);
759 if (prot_ver
!= PROTOCOL_VERSION
) {
760 printk("GDT-EISA: Illegal protocol version\n");
764 ha
->brd_phys
= (ulong32
)eisa_adr
>> 12;
766 outl(0,eisa_adr
+MAILBOXREG
);
767 outl(0,eisa_adr
+MAILBOXREG
+4);
768 outl(0,eisa_adr
+MAILBOXREG
+8);
769 outl(0,eisa_adr
+MAILBOXREG
+12);
772 if ((id
= inl(eisa_adr
+ID0REG
)) == GDT3_ID
) {
775 outl(1,eisa_adr
+MAILBOXREG
+8);
776 outb(0xfe,eisa_adr
+LDOORREG
);
777 retries
= INIT_RETRIES
;
779 while (inb(eisa_adr
+EDOORREG
) != 0xfe) {
780 if (--retries
== 0) {
781 printk("GDT-EISA: Initialization error (get IRQ failed)\n");
786 ha
->irq
= inb(eisa_adr
+MAILBOXREG
);
787 outb(0xff,eisa_adr
+EDOORREG
);
788 TRACE2(("GDT3000/3020: IRQ=%d\n",ha
->irq
));
789 /* check the result */
791 TRACE2(("Unknown IRQ, use IRQ table from cmd line !\n"));
792 for (i
= 0, irq_found
= FALSE
;
793 i
< MAXHA
&& irq
[i
] != 0xff; ++i
) {
794 if (irq
[i
]==10 || irq
[i
]==11 || irq
[i
]==12 || irq
[i
]==14) {
802 printk("GDT-EISA: Can not detect controller IRQ,\n");
803 printk("Use IRQ setting from command line (IRQ = %d)\n",
806 printk("GDT-EISA: Initialization error (unknown IRQ), Enable\n");
807 printk("the controller BIOS or use command line parameters\n");
812 eisacf
= inb(eisa_adr
+EISAREG
) & 7;
813 if (eisacf
> 4) /* level triggered */
815 ha
->irq
= gdth_irq_tab
[eisacf
];
823 static int __init
gdth_init_isa(ulong32 bios_adr
,gdth_ha_str
*ha
)
825 register gdt2_dpram_str
*dp2_ptr
;
827 unchar irq_drq
,prot_ver
;
830 TRACE(("gdth_init_isa() bios adr. %x\n",bios_adr
));
832 ha
->brd
= gdth_mmap(bios_adr
, sizeof(gdt2_dpram_str
));
833 if (ha
->brd
== NULL
) {
834 printk("GDT-ISA: Initialization error (DPMEM remap error)\n");
837 dp2_ptr
= (gdt2_dpram_str
*)ha
->brd
;
838 gdth_writeb(1, &dp2_ptr
->io
.memlock
); /* switch off write protection */
839 /* reset interface area */
840 memset_io((char *)&dp2_ptr
->u
,0,sizeof(dp2_ptr
->u
));
841 if (gdth_readl(&dp2_ptr
->u
) != 0) {
842 printk("GDT-PCI: Initialization error (DPMEM write error)\n");
843 gdth_munmap(ha
->brd
);
847 /* disable board interrupts, read DRQ and IRQ */
848 gdth_writeb(0xff, &dp2_ptr
->io
.irqdel
);
849 gdth_writeb(0x00, &dp2_ptr
->io
.irqen
);
850 gdth_writeb(0x00, &dp2_ptr
->u
.ic
.S_Status
);
851 gdth_writeb(0x00, &dp2_ptr
->u
.ic
.Cmd_Index
);
853 irq_drq
= gdth_readb(&dp2_ptr
->io
.rq
);
854 for (i
=0; i
<3; ++i
) {
855 if ((irq_drq
& 1)==0)
859 ha
->drq
= gdth_drq_tab
[i
];
861 irq_drq
= gdth_readb(&dp2_ptr
->io
.rq
) >> 3;
862 for (i
=1; i
<5; ++i
) {
863 if ((irq_drq
& 1)==0)
867 ha
->irq
= gdth_irq_tab
[i
];
869 /* deinitialize services */
870 gdth_writel(bios_adr
, &dp2_ptr
->u
.ic
.S_Info
[0]);
871 gdth_writeb(0xff, &dp2_ptr
->u
.ic
.S_Cmd_Indx
);
872 gdth_writeb(0, &dp2_ptr
->io
.event
);
873 retries
= INIT_RETRIES
;
875 while (gdth_readb(&dp2_ptr
->u
.ic
.S_Status
) != 0xff) {
876 if (--retries
== 0) {
877 printk("GDT-ISA: Initialization error (DEINIT failed)\n");
878 gdth_munmap(ha
->brd
);
883 prot_ver
= (unchar
)gdth_readl(&dp2_ptr
->u
.ic
.S_Info
[0]);
884 gdth_writeb(0, &dp2_ptr
->u
.ic
.Status
);
885 gdth_writeb(0xff, &dp2_ptr
->io
.irqdel
);
886 if (prot_ver
!= PROTOCOL_VERSION
) {
887 printk("GDT-ISA: Illegal protocol version\n");
888 gdth_munmap(ha
->brd
);
893 ha
->ic_all_size
= sizeof(dp2_ptr
->u
);
895 ha
->brd_phys
= bios_adr
>> 4;
897 /* special request to controller BIOS */
898 gdth_writel(0x00, &dp2_ptr
->u
.ic
.S_Info
[0]);
899 gdth_writel(0x00, &dp2_ptr
->u
.ic
.S_Info
[1]);
900 gdth_writel(0x01, &dp2_ptr
->u
.ic
.S_Info
[2]);
901 gdth_writel(0x00, &dp2_ptr
->u
.ic
.S_Info
[3]);
902 gdth_writeb(0xfe, &dp2_ptr
->u
.ic
.S_Cmd_Indx
);
903 gdth_writeb(0, &dp2_ptr
->io
.event
);
904 retries
= INIT_RETRIES
;
906 while (gdth_readb(&dp2_ptr
->u
.ic
.S_Status
) != 0xfe) {
907 if (--retries
== 0) {
908 printk("GDT-ISA: Initialization error\n");
909 gdth_munmap(ha
->brd
);
914 gdth_writeb(0, &dp2_ptr
->u
.ic
.Status
);
915 gdth_writeb(0xff, &dp2_ptr
->io
.irqdel
);
920 static int __init
gdth_init_pci(gdth_pci_str
*pcistr
,gdth_ha_str
*ha
)
922 register gdt6_dpram_str
*dp6_ptr
;
923 register gdt6c_dpram_str
*dp6c_ptr
;
924 register gdt6m_dpram_str
*dp6m_ptr
;
927 int i
, found
= FALSE
;
929 TRACE(("gdth_init_pci()\n"));
931 ha
->brd_phys
= (pcistr
->bus
<< 8) | (pcistr
->device_fn
& 0xf8);
932 ha
->stype
= (ulong32
)pcistr
->device_id
;
933 ha
->irq
= pcistr
->irq
;
935 if (ha
->stype
<= PCI_DEVICE_ID_VORTEX_GDT6000B
) { /* GDT6000/B */
936 TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr
->dpmem
,ha
->irq
));
937 ha
->brd
= gdth_mmap(pcistr
->dpmem
, sizeof(gdt6_dpram_str
));
938 if (ha
->brd
== NULL
) {
939 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
942 dp6_ptr
= (gdt6_dpram_str
*)ha
->brd
;
943 /* reset interface area */
944 memset_io((char *)&dp6_ptr
->u
,0,sizeof(dp6_ptr
->u
));
945 if (gdth_readl(&dp6_ptr
->u
) != 0) {
946 printk("GDT-PCI: Initialization error (DPMEM write error)\n");
947 gdth_munmap(ha
->brd
);
951 /* disable board interrupts, deinit services */
952 gdth_writeb(0xff, &dp6_ptr
->io
.irqdel
);
953 gdth_writeb(0x00, &dp6_ptr
->io
.irqen
);;
954 gdth_writeb(0x00, &dp6_ptr
->u
.ic
.S_Status
);
955 gdth_writeb(0x00, &dp6_ptr
->u
.ic
.Cmd_Index
);
957 gdth_writel(pcistr
->dpmem
, &dp6_ptr
->u
.ic
.S_Info
[0]);
958 gdth_writeb(0xff, &dp6_ptr
->u
.ic
.S_Cmd_Indx
);
959 gdth_writeb(0, &dp6_ptr
->io
.event
);
960 retries
= INIT_RETRIES
;
962 while (gdth_readb(&dp6_ptr
->u
.ic
.S_Status
) != 0xff) {
963 if (--retries
== 0) {
964 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
965 gdth_munmap(ha
->brd
);
970 prot_ver
= (unchar
)gdth_readl(&dp6_ptr
->u
.ic
.S_Info
[0]);
971 gdth_writeb(0, &dp6_ptr
->u
.ic
.S_Status
);
972 gdth_writeb(0xff, &dp6_ptr
->io
.irqdel
);
973 if (prot_ver
!= PROTOCOL_VERSION
) {
974 printk("GDT-PCI: Illegal protocol version\n");
975 gdth_munmap(ha
->brd
);
980 ha
->ic_all_size
= sizeof(dp6_ptr
->u
);
982 /* special command to controller BIOS */
983 gdth_writel(0x00, &dp6_ptr
->u
.ic
.S_Info
[0]);
984 gdth_writel(0x00, &dp6_ptr
->u
.ic
.S_Info
[1]);
985 gdth_writel(0x01, &dp6_ptr
->u
.ic
.S_Info
[2]);
986 gdth_writel(0x00, &dp6_ptr
->u
.ic
.S_Info
[3]);
987 gdth_writeb(0xfe, &dp6_ptr
->u
.ic
.S_Cmd_Indx
);
988 gdth_writeb(0, &dp6_ptr
->io
.event
);
989 retries
= INIT_RETRIES
;
991 while (gdth_readb(&dp6_ptr
->u
.ic
.S_Status
) != 0xfe) {
992 if (--retries
== 0) {
993 printk("GDT-PCI: Initialization error\n");
994 gdth_munmap(ha
->brd
);
999 gdth_writeb(0, &dp6_ptr
->u
.ic
.S_Status
);
1000 gdth_writeb(0xff, &dp6_ptr
->io
.irqdel
);
1002 } else if (ha
->stype
<= PCI_DEVICE_ID_VORTEX_GDT6555
) { /* GDT6110, ... */
1003 ha
->plx
= (gdt6c_plx_regs
*)pcistr
->io
;
1004 TRACE2(("init_pci_new() dpmem %lx irq %d\n",
1005 pcistr
->dpmem
,ha
->irq
));
1006 ha
->brd
= gdth_mmap(pcistr
->dpmem
, sizeof(gdt6c_dpram_str
));
1007 if (ha
->brd
== NULL
) {
1008 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1009 gdth_munmap(ha
->brd
);
1012 dp6c_ptr
= (gdt6c_dpram_str
*)ha
->brd
;
1013 /* reset interface area */
1014 memset_io((char *)&dp6c_ptr
->u
,0,sizeof(dp6c_ptr
->u
));
1015 if (gdth_readl(&dp6c_ptr
->u
) != 0) {
1016 printk("GDT-PCI: Initialization error (DPMEM write error)\n");
1017 gdth_munmap(ha
->brd
);
1021 /* disable board interrupts, deinit services */
1022 outb(0x00,PTR2USHORT(&ha
->plx
->control1
));
1023 outb(0xff,PTR2USHORT(&ha
->plx
->edoor_reg
));
1025 gdth_writeb(0x00, &dp6c_ptr
->u
.ic
.S_Status
);
1026 gdth_writeb(0x00, &dp6c_ptr
->u
.ic
.Cmd_Index
);
1028 gdth_writel(pcistr
->dpmem
, &dp6c_ptr
->u
.ic
.S_Info
[0]);
1029 gdth_writeb(0xff, &dp6c_ptr
->u
.ic
.S_Cmd_Indx
);
1031 outb(1,PTR2USHORT(&ha
->plx
->ldoor_reg
));
1033 retries
= INIT_RETRIES
;
1035 while (gdth_readb(&dp6c_ptr
->u
.ic
.S_Status
) != 0xff) {
1036 if (--retries
== 0) {
1037 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
1038 gdth_munmap(ha
->brd
);
1043 prot_ver
= (unchar
)gdth_readl(&dp6c_ptr
->u
.ic
.S_Info
[0]);
1044 gdth_writeb(0, &dp6c_ptr
->u
.ic
.Status
);
1045 if (prot_ver
!= PROTOCOL_VERSION
) {
1046 printk("GDT-PCI: Illegal protocol version\n");
1047 gdth_munmap(ha
->brd
);
1051 ha
->type
= GDT_PCINEW
;
1052 ha
->ic_all_size
= sizeof(dp6c_ptr
->u
);
1054 /* special command to controller BIOS */
1055 gdth_writel(0x00, &dp6c_ptr
->u
.ic
.S_Info
[0]);
1056 gdth_writel(0x00, &dp6c_ptr
->u
.ic
.S_Info
[1]);
1057 gdth_writel(0x01, &dp6c_ptr
->u
.ic
.S_Info
[2]);
1058 gdth_writel(0x00, &dp6c_ptr
->u
.ic
.S_Info
[3]);
1059 gdth_writeb(0xfe, &dp6c_ptr
->u
.ic
.S_Cmd_Indx
);
1061 outb(1,PTR2USHORT(&ha
->plx
->ldoor_reg
));
1063 retries
= INIT_RETRIES
;
1065 while (gdth_readb(&dp6c_ptr
->u
.ic
.S_Status
) != 0xfe) {
1066 if (--retries
== 0) {
1067 printk("GDT-PCI: Initialization error\n");
1068 gdth_munmap(ha
->brd
);
1073 gdth_writeb(0, &dp6c_ptr
->u
.ic
.S_Status
);
1076 TRACE2(("init_pci_mpr() dpmem %lx irq %d\n",pcistr
->dpmem
,ha
->irq
));
1077 ha
->brd
= gdth_mmap(pcistr
->dpmem
, sizeof(gdt6m_dpram_str
));
1078 if (ha
->brd
== NULL
) {
1079 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1083 /* check and reset interface area */
1084 dp6m_ptr
= (gdt6m_dpram_str
*)ha
->brd
;
1085 gdth_writel(DPMEM_MAGIC
, &dp6m_ptr
->u
);
1086 if (gdth_readl(&dp6m_ptr
->u
) != DPMEM_MAGIC
) {
1087 printk("GDT-PCI: Cannot access DPMEM at 0x%x (shadowed?)\n",
1088 (int)pcistr
->dpmem
);
1090 for (i
= 0xC8000; i
< 0xE8000; i
+= 0x4000) {
1091 gdth_munmap(ha
->brd
);
1092 ha
->brd
= gdth_mmap(i
, sizeof(ushort
));
1093 if (ha
->brd
== NULL
) {
1094 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1097 if (gdth_readw(ha
->brd
) != 0xffff) {
1098 TRACE2(("init_pci_mpr() address 0x%x busy\n", i
));
1101 gdth_munmap(ha
->brd
);
1102 #if LINUX_VERSION_CODE >= 0x2015C
1103 pci_write_config_dword(pcistr
->pdev
,
1104 PCI_BASE_ADDRESS_0
, i
);
1106 pcibios_write_config_dword(pcistr
->bus
, pcistr
->device_fn
,
1107 PCI_BASE_ADDRESS_0
, i
);
1109 ha
->brd
= gdth_mmap(i
, sizeof(gdt6m_dpram_str
));
1110 if (ha
->brd
== NULL
) {
1111 printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
1114 dp6m_ptr
= (gdt6m_dpram_str
*)ha
->brd
;
1115 gdth_writel(DPMEM_MAGIC
, &dp6m_ptr
->u
);
1116 if (gdth_readl(&dp6m_ptr
->u
) == DPMEM_MAGIC
) {
1117 printk("GDT-PCI: Use free address at 0x%x\n", i
);
1123 printk("GDT-PCI: No free address found!\n");
1124 gdth_munmap(ha
->brd
);
1128 memset_io((char *)&dp6m_ptr
->u
,0,sizeof(dp6m_ptr
->u
));
1130 /* disable board interrupts, deinit services */
1131 gdth_writeb(gdth_readb(&dp6m_ptr
->i960r
.edoor_en_reg
) | 4,
1132 &dp6m_ptr
->i960r
.edoor_en_reg
);
1133 gdth_writeb(0xff, &dp6m_ptr
->i960r
.edoor_reg
);
1134 gdth_writeb(0x00, &dp6m_ptr
->u
.ic
.S_Status
);
1135 gdth_writeb(0x00, &dp6m_ptr
->u
.ic
.Cmd_Index
);
1137 gdth_writel(pcistr
->dpmem
, &dp6m_ptr
->u
.ic
.S_Info
[0]);
1138 gdth_writeb(0xff, &dp6m_ptr
->u
.ic
.S_Cmd_Indx
);
1139 gdth_writeb(1, &dp6m_ptr
->i960r
.ldoor_reg
);
1140 retries
= INIT_RETRIES
;
1142 while (gdth_readb(&dp6m_ptr
->u
.ic
.S_Status
) != 0xff) {
1143 if (--retries
== 0) {
1144 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
1145 gdth_munmap(ha
->brd
);
1150 prot_ver
= (unchar
)gdth_readl(&dp6m_ptr
->u
.ic
.S_Info
[0]);
1151 gdth_writeb(0, &dp6m_ptr
->u
.ic
.S_Status
);
1152 if (prot_ver
!= PROTOCOL_VERSION
) {
1153 printk("GDT-PCI: Illegal protocol version\n");
1154 gdth_munmap(ha
->brd
);
1158 ha
->type
= GDT_PCIMPR
;
1159 ha
->ic_all_size
= sizeof(dp6m_ptr
->u
);
1161 /* special command to controller BIOS */
1162 gdth_writel(0x00, &dp6m_ptr
->u
.ic
.S_Info
[0]);
1163 gdth_writel(0x00, &dp6m_ptr
->u
.ic
.S_Info
[1]);
1164 gdth_writel(0x01, &dp6m_ptr
->u
.ic
.S_Info
[2]);
1165 gdth_writel(0x00, &dp6m_ptr
->u
.ic
.S_Info
[3]);
1166 gdth_writeb(0xfe, &dp6m_ptr
->u
.ic
.S_Cmd_Indx
);
1167 gdth_writeb(1, &dp6m_ptr
->i960r
.ldoor_reg
);
1168 retries
= INIT_RETRIES
;
1170 while (gdth_readb(&dp6m_ptr
->u
.ic
.S_Status
) != 0xfe) {
1171 if (--retries
== 0) {
1172 printk("GDT-PCI: Initialization error\n");
1173 gdth_munmap(ha
->brd
);
1178 gdth_writeb(0, &dp6m_ptr
->u
.ic
.S_Status
);
1185 /* controller protocol functions */
1187 static void __init
gdth_enable_int(int hanum
)
1191 gdt2_dpram_str
*dp2_ptr
;
1192 gdt6_dpram_str
*dp6_ptr
;
1193 gdt6m_dpram_str
*dp6m_ptr
;
1195 TRACE(("gdth_enable_int() hanum %d\n",hanum
));
1196 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1197 GDTH_LOCK_HA(ha
, flags
);
1199 if (ha
->type
== GDT_EISA
) {
1200 outb(0xff, ha
->bmic
+ EDOORREG
);
1201 outb(0xff, ha
->bmic
+ EDENABREG
);
1202 outb(0x01, ha
->bmic
+ EINTENABREG
);
1203 } else if (ha
->type
== GDT_ISA
) {
1204 dp2_ptr
= (gdt2_dpram_str
*)ha
->brd
;
1205 gdth_writeb(1, &dp2_ptr
->io
.irqdel
);
1206 gdth_writeb(0, &dp2_ptr
->u
.ic
.Cmd_Index
);
1207 gdth_writeb(1, &dp2_ptr
->io
.irqen
);
1208 } else if (ha
->type
== GDT_PCI
) {
1209 dp6_ptr
= (gdt6_dpram_str
*)ha
->brd
;
1210 gdth_writeb(1, &dp6_ptr
->io
.irqdel
);
1211 gdth_writeb(0, &dp6_ptr
->u
.ic
.Cmd_Index
);
1212 gdth_writeb(1, &dp6_ptr
->io
.irqen
);
1213 } else if (ha
->type
== GDT_PCINEW
) {
1214 outb(0xff, PTR2USHORT(&ha
->plx
->edoor_reg
));
1215 outb(0x03, PTR2USHORT(&ha
->plx
->control1
));
1216 } else if (ha
->type
== GDT_PCIMPR
) {
1217 dp6m_ptr
= (gdt6m_dpram_str
*)ha
->brd
;
1218 gdth_writeb(0xff, &dp6m_ptr
->i960r
.edoor_reg
);
1219 gdth_writeb(gdth_readb(&dp6m_ptr
->i960r
.edoor_en_reg
) & ~4,
1220 &dp6m_ptr
->i960r
.edoor_en_reg
);
1222 GDTH_UNLOCK_HA(ha
, flags
);
1226 static int gdth_get_status(unchar
*pIStatus
,int irq
)
1228 register gdth_ha_str
*ha
;
1231 TRACE(("gdth_get_status() irq %d ctr_count %d\n",
1232 irq
,gdth_ctr_count
));
1235 for (i
=0; i
<gdth_ctr_count
; ++i
) {
1236 ha
= HADATA(gdth_ctr_tab
[i
]);
1237 if (ha
->irq
!= (unchar
)irq
) /* check IRQ */
1239 if (ha
->type
== GDT_EISA
)
1240 *pIStatus
= inb((ushort
)ha
->bmic
+ EDOORREG
);
1241 else if (ha
->type
== GDT_ISA
)
1243 gdth_readb(&((gdt2_dpram_str
*)ha
->brd
)->u
.ic
.Cmd_Index
);
1244 else if (ha
->type
== GDT_PCI
)
1246 gdth_readb(&((gdt6_dpram_str
*)ha
->brd
)->u
.ic
.Cmd_Index
);
1247 else if (ha
->type
== GDT_PCINEW
)
1248 *pIStatus
= inb(PTR2USHORT(&ha
->plx
->edoor_reg
));
1249 else if (ha
->type
== GDT_PCIMPR
)
1251 gdth_readb(&((gdt6m_dpram_str
*)ha
->brd
)->i960r
.edoor_reg
);
1254 return i
; /* board found */
1260 static int gdth_test_busy(int hanum
)
1262 register gdth_ha_str
*ha
;
1263 register int gdtsema0
= 0;
1265 TRACE(("gdth_test_busy() hanum %d\n",hanum
));
1267 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1268 if (ha
->type
== GDT_EISA
)
1269 gdtsema0
= (int)inb(ha
->bmic
+ SEMA0REG
);
1270 else if (ha
->type
== GDT_ISA
)
1271 gdtsema0
= (int)gdth_readb(&((gdt2_dpram_str
*)ha
->brd
)->u
.ic
.Sema0
);
1272 else if (ha
->type
== GDT_PCI
)
1273 gdtsema0
= (int)gdth_readb(&((gdt6_dpram_str
*)ha
->brd
)->u
.ic
.Sema0
);
1274 else if (ha
->type
== GDT_PCINEW
)
1275 gdtsema0
= (int)inb(PTR2USHORT(&ha
->plx
->sema0_reg
));
1276 else if (ha
->type
== GDT_PCIMPR
)
1278 (int)gdth_readb(&((gdt6m_dpram_str
*)ha
->brd
)->i960r
.sema0_reg
);
1280 return (gdtsema0
& 1);
1284 static int gdth_get_cmd_index(int hanum
)
1286 register gdth_ha_str
*ha
;
1289 TRACE(("gdth_get_cmd_index() hanum %d\n",hanum
));
1291 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1292 for (i
=0; i
<GDTH_MAXCMDS
; ++i
) {
1293 if (ha
->cmd_tab
[i
].cmnd
== UNUSED_CMND
) {
1294 ha
->cmd_tab
[i
].cmnd
= ha
->pccb
->RequestBuffer
;
1295 ha
->cmd_tab
[i
].service
= ha
->pccb
->Service
;
1296 ha
->pccb
->CommandIndex
= (ulong32
)i
+2;
1304 static void gdth_set_sema0(int hanum
)
1306 register gdth_ha_str
*ha
;
1308 TRACE(("gdth_set_sema0() hanum %d\n",hanum
));
1310 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1311 if (ha
->type
== GDT_EISA
) {
1312 outb(1, ha
->bmic
+ SEMA0REG
);
1313 } else if (ha
->type
== GDT_ISA
) {
1314 gdth_writeb(1, &((gdt2_dpram_str
*)ha
->brd
)->u
.ic
.Sema0
);
1315 } else if (ha
->type
== GDT_PCI
) {
1316 gdth_writeb(1, &((gdt6_dpram_str
*)ha
->brd
)->u
.ic
.Sema0
);
1317 } else if (ha
->type
== GDT_PCINEW
) {
1318 outb(1, PTR2USHORT(&ha
->plx
->sema0_reg
));
1319 } else if (ha
->type
== GDT_PCIMPR
) {
1320 gdth_writeb(1, &((gdt6m_dpram_str
*)ha
->brd
)->i960r
.sema0_reg
);
1325 static void gdth_copy_command(int hanum
)
1327 register gdth_ha_str
*ha
;
1328 register gdth_cmd_str
*cmd_ptr
;
1329 register gdt6m_dpram_str
*dp6m_ptr
;
1330 register gdt6c_dpram_str
*dp6c_ptr
;
1331 gdt6_dpram_str
*dp6_ptr
;
1332 gdt2_dpram_str
*dp2_ptr
;
1333 ushort cp_count
,dp_offset
,cmd_no
;
1335 TRACE(("gdth_copy_command() hanum %d\n",hanum
));
1337 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1338 cp_count
= ha
->cmd_len
;
1339 dp_offset
= ha
->cmd_offs_dpmem
;
1340 cmd_no
= ha
->cmd_cnt
;
1344 if (ha
->type
== GDT_EISA
)
1345 return; /* no DPMEM, no copy */
1347 /* set cpcount dword aligned */
1349 cp_count
+= (4 - (cp_count
& 3));
1351 ha
->cmd_offs_dpmem
+= cp_count
;
1353 /* set offset and service, copy command to DPMEM */
1354 if (ha
->type
== GDT_ISA
) {
1355 dp2_ptr
= (gdt2_dpram_str
*)ha
->brd
;
1356 gdth_writew(dp_offset
+ DPMEM_COMMAND_OFFSET
,
1357 &dp2_ptr
->u
.ic
.comm_queue
[cmd_no
].offset
);
1358 gdth_writew((ushort
)cmd_ptr
->Service
,
1359 &dp2_ptr
->u
.ic
.comm_queue
[cmd_no
].serv_id
);
1360 memcpy_toio(&dp2_ptr
->u
.ic
.gdt_dpr_cmd
[dp_offset
],cmd_ptr
,cp_count
);
1361 } else if (ha
->type
== GDT_PCI
) {
1362 dp6_ptr
= (gdt6_dpram_str
*)ha
->brd
;
1363 gdth_writew(dp_offset
+ DPMEM_COMMAND_OFFSET
,
1364 &dp6_ptr
->u
.ic
.comm_queue
[cmd_no
].offset
);
1365 gdth_writew((ushort
)cmd_ptr
->Service
,
1366 &dp6_ptr
->u
.ic
.comm_queue
[cmd_no
].serv_id
);
1367 memcpy_toio(&dp6_ptr
->u
.ic
.gdt_dpr_cmd
[dp_offset
],cmd_ptr
,cp_count
);
1368 } else if (ha
->type
== GDT_PCINEW
) {
1369 dp6c_ptr
= (gdt6c_dpram_str
*)ha
->brd
;
1370 gdth_writew(dp_offset
+ DPMEM_COMMAND_OFFSET
,
1371 &dp6c_ptr
->u
.ic
.comm_queue
[cmd_no
].offset
);
1372 gdth_writew((ushort
)cmd_ptr
->Service
,
1373 &dp6c_ptr
->u
.ic
.comm_queue
[cmd_no
].serv_id
);
1374 memcpy_toio(&dp6c_ptr
->u
.ic
.gdt_dpr_cmd
[dp_offset
],cmd_ptr
,cp_count
);
1375 } else if (ha
->type
== GDT_PCIMPR
) {
1376 dp6m_ptr
= (gdt6m_dpram_str
*)ha
->brd
;
1377 gdth_writew(dp_offset
+ DPMEM_COMMAND_OFFSET
,
1378 &dp6m_ptr
->u
.ic
.comm_queue
[cmd_no
].offset
);
1379 gdth_writew((ushort
)cmd_ptr
->Service
,
1380 &dp6m_ptr
->u
.ic
.comm_queue
[cmd_no
].serv_id
);
1381 memcpy_toio(&dp6m_ptr
->u
.ic
.gdt_dpr_cmd
[dp_offset
],cmd_ptr
,cp_count
);
1386 static void gdth_release_event(int hanum
)
1388 register gdth_ha_str
*ha
;
1390 TRACE(("gdth_release_event() hanum %d\n",hanum
));
1391 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1393 #ifdef GDTH_STATISTICS
1396 for (i
=0,j
=0; j
<GDTH_MAXCMDS
; ++j
) {
1397 if (ha
->cmd_tab
[j
].cmnd
!= UNUSED_CMND
)
1400 if (max_index
< i
) {
1402 TRACE3(("GDT: max_index = %d\n",(ushort
)i
));
1407 if (ha
->pccb
->OpCode
== GDT_INIT
)
1408 ha
->pccb
->Service
|= 0x80;
1410 if (ha
->type
== GDT_EISA
) {
1411 if (ha
->pccb
->OpCode
== GDT_INIT
) /* store DMA buffer */
1412 outl(virt_to_bus(ha
->pccb
), ha
->bmic
+ MAILBOXREG
);
1413 outb(ha
->pccb
->Service
, ha
->bmic
+ LDOORREG
);
1414 } else if (ha
->type
== GDT_ISA
) {
1415 gdth_writeb(0, &((gdt2_dpram_str
*)ha
->brd
)->io
.event
);
1416 } else if (ha
->type
== GDT_PCI
) {
1417 gdth_writeb(0, &((gdt6_dpram_str
*)ha
->brd
)->io
.event
);
1418 } else if (ha
->type
== GDT_PCINEW
) {
1419 outb(1, PTR2USHORT(&ha
->plx
->ldoor_reg
));
1420 } else if (ha
->type
== GDT_PCIMPR
) {
1421 gdth_writeb(1, &((gdt6m_dpram_str
*)ha
->brd
)->i960r
.ldoor_reg
);
1426 static int gdth_wait(int hanum
,int index
,ulong32 time
)
1429 int answer_found
= FALSE
;
1431 TRACE(("gdth_wait() hanum %d index %d time %d\n",hanum
,index
,time
));
1433 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1435 return 1; /* no wait required */
1437 gdth_from_wait
= TRUE
;
1439 #if LINUX_VERSION_CODE >= 0x010346
1440 gdth_interrupt((int)ha
->irq
,ha
,NULL
);
1442 gdth_interrupt((int)ha
->irq
,NULL
);
1444 if (wait_hanum
==hanum
&& wait_index
==index
) {
1445 answer_found
= TRUE
;
1450 gdth_from_wait
= FALSE
;
1452 while (gdth_test_busy(hanum
))
1455 return (answer_found
);
1459 static int gdth_internal_cmd(int hanum
,unchar service
,ushort opcode
,ulong32 p1
,
1460 ulong32 p2
,ulong32 p3
)
1462 register gdth_ha_str
*ha
;
1463 register gdth_cmd_str
*cmd_ptr
;
1466 TRACE2(("gdth_internal_cmd() service %d opcode %d\n",service
,opcode
));
1468 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1470 memset((char*)cmd_ptr
,0,sizeof(gdth_cmd_str
));
1473 for (retries
= INIT_RETRIES
;;) {
1474 cmd_ptr
->Service
= service
;
1475 cmd_ptr
->RequestBuffer
= INTERNAL_CMND
;
1476 if (!(index
=gdth_get_cmd_index(hanum
))) {
1477 TRACE(("GDT: No free command index found\n"));
1480 gdth_set_sema0(hanum
);
1481 cmd_ptr
->OpCode
= opcode
;
1482 cmd_ptr
->BoardNode
= LOCALBOARD
;
1483 if (service
== CACHESERVICE
) {
1484 if (opcode
== GDT_IOCTL
) {
1485 cmd_ptr
->u
.ioctl
.subfunc
= p1
;
1486 cmd_ptr
->u
.ioctl
.channel
= p2
;
1487 cmd_ptr
->u
.ioctl
.param_size
= (ushort
)p3
;
1488 cmd_ptr
->u
.ioctl
.p_param
= virt_to_bus(ha
->pscratch
);
1490 cmd_ptr
->u
.cache
.DeviceNo
= (ushort
)p1
;
1491 cmd_ptr
->u
.cache
.BlockNo
= p2
;
1493 } else if (service
== SCSIRAWSERVICE
) {
1494 cmd_ptr
->u
.raw
.direction
= p1
;
1495 cmd_ptr
->u
.raw
.bus
= (unchar
)p2
;
1496 cmd_ptr
->u
.raw
.target
= (unchar
)p3
;
1497 cmd_ptr
->u
.raw
.lun
= (unchar
)(p3
>> 8);
1499 ha
->cmd_len
= sizeof(gdth_cmd_str
);
1500 ha
->cmd_offs_dpmem
= 0;
1502 gdth_copy_command(hanum
);
1503 gdth_release_event(hanum
);
1505 if (!gdth_wait(hanum
,index
,INIT_TIMEOUT
)) {
1506 printk("GDT: Initialization error (timeout service %d)\n",service
);
1509 if (ha
->status
!= S_BSY
|| --retries
== 0)
1514 return (ha
->status
!= S_OK
? 0:1);
1518 /* search for devices */
1520 static int __init
gdth_search_drives(int hanum
)
1522 register gdth_ha_str
*ha
;
1524 int drv_cyls
, drv_hds
, drv_secs
;
1526 ulong32 drv_cnt
, drv_no
, j
;
1527 gdth_getch_str
*chn
;
1528 gdth_drlist_str
*drl
;
1529 gdth_iochan_str
*ioc
;
1530 gdth_raw_iochan_str
*iocr
;
1531 gdth_arraylist_str
*alst
;
1533 TRACE(("gdth_search_drives() hanum %d\n",hanum
));
1534 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1536 /* initialize controller services, at first: screen service */
1537 if (!gdth_internal_cmd(hanum
,SCREENSERVICE
,GDT_INIT
,0,0,0)) {
1538 printk("GDT: Initialization error screen service (code %d)\n",
1542 TRACE2(("gdth_search_drives(): SCREENSERVICE initialized\n"));
1544 /* initialize cache service */
1545 if (!gdth_internal_cmd(hanum
,CACHESERVICE
,GDT_INIT
,LINUX_OS
,0,0)) {
1546 printk("GDT: Initialization error cache service (code %d)\n",
1550 TRACE2(("gdth_search_drives(): CACHESERVICE initialized\n"));
1551 cdev_cnt
= (ushort
)ha
->info
;
1553 /* mount all cache devices */
1554 gdth_internal_cmd(hanum
,CACHESERVICE
,GDT_MOUNT
,0xffff,1,0);
1555 TRACE2(("gdth_search_drives(): mountall CACHESERVICE OK\n"));
1557 /* initialize cache service after mountall */
1558 if (!gdth_internal_cmd(hanum
,CACHESERVICE
,GDT_INIT
,LINUX_OS
,0,0)) {
1559 printk("GDT: Initialization error cache service (code %d)\n",
1563 TRACE2(("gdth_search_drives() CACHES. init. after mountall\n"));
1564 cdev_cnt
= (ushort
)ha
->info
;
1566 /* detect number of buses - try new IOCTL */
1567 iocr
= (gdth_raw_iochan_str
*)ha
->pscratch
;
1568 iocr
->hdr
.version
= 0xffffffff;
1569 iocr
->hdr
.list_entries
= MAXBUS
;
1570 iocr
->hdr
.first_chan
= 0;
1571 iocr
->hdr
.last_chan
= MAXBUS
-1;
1572 iocr
->hdr
.list_offset
= GDTOFFSOF(gdth_raw_iochan_str
, list
[0]);
1573 if (gdth_internal_cmd(hanum
,CACHESERVICE
,GDT_IOCTL
,IOCHAN_RAW_DESC
,
1574 INVALID_CHANNEL
,sizeof(gdth_raw_iochan_str
))) {
1575 TRACE2(("IOCHAN_RAW_DESC supported!\n"));
1576 ha
->bus_cnt
= iocr
->hdr
.chan_count
;
1577 for (bus_no
= 0; bus_no
< ha
->bus_cnt
; ++bus_no
) {
1578 if (iocr
->list
[bus_no
].proc_id
< MAXID
)
1579 ha
->bus_id
[bus_no
] = iocr
->list
[bus_no
].proc_id
;
1581 ha
->bus_id
[bus_no
] = 0xff;
1585 chn
= (gdth_getch_str
*)ha
->pscratch
;
1586 for (bus_no
= 0; bus_no
< MAXBUS
; ++bus_no
) {
1587 chn
->channel_no
= bus_no
;
1588 if (!gdth_internal_cmd(hanum
,CACHESERVICE
,GDT_IOCTL
,
1589 SCSI_CHAN_CNT
| L_CTRL_PATTERN
,
1590 IO_CHANNEL
| INVALID_CHANNEL
,
1591 sizeof(gdth_getch_str
))) {
1593 printk("GDT: Error detecting channel count (0x%x)\n",
1599 if (chn
->siop_id
< MAXID
)
1600 ha
->bus_id
[bus_no
] = chn
->siop_id
;
1602 ha
->bus_id
[bus_no
] = 0xff;
1604 ha
->bus_cnt
= (unchar
)bus_no
;
1606 TRACE2(("gdth_search_drives() %d channels\n",ha
->bus_cnt
));
1608 /* read cache configuration */
1609 if (!gdth_internal_cmd(hanum
,CACHESERVICE
,GDT_IOCTL
,CACHE_INFO
,
1610 INVALID_CHANNEL
,sizeof(gdth_cinfo_str
))) {
1611 printk("GDT: Initialization error cache service (code %d)\n",
1615 ha
->cpar
= ((gdth_cinfo_str
*)ha
->pscratch
)->cpar
;
1616 TRACE2(("gdth_search_drives() cinfo: vs %x sta %d str %d dw %d b %d\n",
1617 ha
->cpar
.version
,ha
->cpar
.state
,ha
->cpar
.strategy
,
1618 ha
->cpar
.write_back
,ha
->cpar
.block_size
));
1620 /* read board info and features */
1621 ha
->more_proc
= FALSE
;
1622 if (gdth_internal_cmd(hanum
,CACHESERVICE
,GDT_IOCTL
,BOARD_INFO
,
1623 INVALID_CHANNEL
,sizeof(gdth_binfo_str
))) {
1624 ha
->binfo
= *(gdth_binfo_str
*)ha
->pscratch
;
1625 if (gdth_internal_cmd(hanum
,CACHESERVICE
,GDT_IOCTL
,BOARD_FEATURES
,
1626 INVALID_CHANNEL
,sizeof(gdth_bfeat_str
))) {
1627 TRACE2(("BOARD_INFO/BOARD_FEATURES supported\n"));
1628 ha
->bfeat
= *(gdth_bfeat_str
*)ha
->pscratch
;
1629 ha
->more_proc
= TRUE
;
1632 TRACE2(("BOARD_INFO requires firmware >= 1.10/2.08\n"));
1633 strcpy(ha
->binfo
.type_string
, gdth_ctr_name(hanum
));
1635 TRACE2(("Controller name: %s\n",ha
->binfo
.type_string
));
1637 /* read more informations */
1638 if (ha
->more_proc
) {
1639 /* physical drives, channel addresses */
1640 ioc
= (gdth_iochan_str
*)ha
->pscratch
;
1641 ioc
->hdr
.version
= 0xffffffff;
1642 ioc
->hdr
.list_entries
= MAXBUS
;
1643 ioc
->hdr
.first_chan
= 0;
1644 ioc
->hdr
.last_chan
= MAXBUS
-1;
1645 ioc
->hdr
.list_offset
= GDTOFFSOF(gdth_iochan_str
, list
[0]);
1646 if (gdth_internal_cmd(hanum
,CACHESERVICE
,GDT_IOCTL
,IOCHAN_DESC
,
1647 INVALID_CHANNEL
,sizeof(gdth_iochan_str
))) {
1648 for (bus_no
= 0; bus_no
< ha
->bus_cnt
; ++bus_no
) {
1649 ha
->raw
[bus_no
].address
= ioc
->list
[bus_no
].address
;
1650 ha
->raw
[bus_no
].local_no
= ioc
->list
[bus_no
].local_no
;
1653 for (bus_no
= 0; bus_no
< ha
->bus_cnt
; ++bus_no
) {
1654 ha
->raw
[bus_no
].address
= IO_CHANNEL
;
1655 ha
->raw
[bus_no
].local_no
= bus_no
;
1658 for (bus_no
= 0; bus_no
< ha
->bus_cnt
; ++bus_no
) {
1659 chn
= (gdth_getch_str
*)ha
->pscratch
;
1660 chn
->channel_no
= ha
->raw
[bus_no
].local_no
;
1661 if (gdth_internal_cmd(hanum
,CACHESERVICE
,GDT_IOCTL
,
1662 SCSI_CHAN_CNT
| L_CTRL_PATTERN
,
1663 ha
->raw
[bus_no
].address
| INVALID_CHANNEL
,
1664 sizeof(gdth_getch_str
))) {
1665 ha
->raw
[bus_no
].pdev_cnt
= chn
->drive_cnt
;
1666 TRACE2(("Channel %d: %d phys. drives\n",
1667 bus_no
,chn
->drive_cnt
));
1669 if (ha
->raw
[bus_no
].pdev_cnt
> 0) {
1670 drl
= (gdth_drlist_str
*)ha
->pscratch
;
1671 drl
->sc_no
= ha
->raw
[bus_no
].local_no
;
1672 drl
->sc_cnt
= ha
->raw
[bus_no
].pdev_cnt
;
1673 if (gdth_internal_cmd(hanum
,CACHESERVICE
,GDT_IOCTL
,
1674 SCSI_DR_LIST
| L_CTRL_PATTERN
,
1675 ha
->raw
[bus_no
].address
| INVALID_CHANNEL
,
1676 sizeof(gdth_drlist_str
))) {
1677 for (j
= 0; j
< ha
->raw
[bus_no
].pdev_cnt
; ++j
)
1678 ha
->raw
[bus_no
].id_list
[j
] = drl
->sc_list
[j
];
1680 ha
->raw
[bus_no
].pdev_cnt
= 0;
1685 /* logical drives */
1686 if (gdth_internal_cmd(hanum
,CACHESERVICE
,GDT_IOCTL
,CACHE_DRV_CNT
,
1687 INVALID_CHANNEL
,sizeof(ulong32
))) {
1688 drv_cnt
= *(ulong32
*)ha
->pscratch
;
1689 if (gdth_internal_cmd(hanum
,CACHESERVICE
,GDT_IOCTL
,CACHE_DRV_LIST
,
1690 INVALID_CHANNEL
,drv_cnt
* sizeof(ulong32
))) {
1691 for (j
= 0; j
< drv_cnt
; ++j
) {
1692 drv_no
= ((ulong32
*)ha
->pscratch
)[j
];
1693 if (drv_no
< MAX_HDRIVES
) {
1694 ha
->hdr
[drv_no
].is_logdrv
= TRUE
;
1695 TRACE2(("Drive %d is log. drive\n",drv_no
));
1699 if (gdth_internal_cmd(hanum
,CACHESERVICE
,GDT_IOCTL
,
1700 ARRAY_DRV_LIST
| LA_CTRL_PATTERN
,
1701 0, 35 * sizeof(gdth_arraylist_str
))) {
1702 for (j
= 0; j
< 35; ++j
) {
1703 alst
= &((gdth_arraylist_str
*)ha
->pscratch
)[j
];
1704 ha
->hdr
[j
].is_arraydrv
= alst
->is_arrayd
;
1705 ha
->hdr
[j
].is_master
= alst
->is_master
;
1706 ha
->hdr
[j
].is_parity
= alst
->is_parity
;
1707 ha
->hdr
[j
].is_hotfix
= alst
->is_hotfix
;
1708 ha
->hdr
[j
].master_no
= alst
->cd_handle
;
1714 /* initialize raw service */
1715 if (!gdth_internal_cmd(hanum
,SCSIRAWSERVICE
,GDT_INIT
,0,0,0)) {
1716 printk("GDT: Initialization error raw service (code %d)\n",
1720 TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n"));
1722 /* set/get features raw service (scatter/gather) */
1724 if (gdth_internal_cmd(hanum
,SCSIRAWSERVICE
,GDT_SET_FEAT
,SCATTER_GATHER
,
1726 TRACE2(("gdth_search_drives(): set features RAWSERVICE OK\n"));
1727 if (gdth_internal_cmd(hanum
,SCSIRAWSERVICE
,GDT_GET_FEAT
,0,0,0)) {
1728 TRACE2(("gdth_search_dr(): get feat RAWSERVICE %d\n",
1730 ha
->raw_feat
= (ushort
)ha
->info
;
1734 /* set/get features cache service (equal to raw service) */
1735 if (gdth_internal_cmd(hanum
,CACHESERVICE
,GDT_SET_FEAT
,0,
1736 SCATTER_GATHER
,0)) {
1737 TRACE2(("gdth_search_drives(): set features CACHESERVICE OK\n"));
1738 if (gdth_internal_cmd(hanum
,CACHESERVICE
,GDT_GET_FEAT
,0,0,0)) {
1739 TRACE2(("gdth_search_dr(): get feat CACHESERV. %d\n",
1741 ha
->cache_feat
= (ushort
)ha
->info
;
1745 /* reserve drives for raw service */
1746 if (reserve_mode
!= 0) {
1747 gdth_internal_cmd(hanum
,SCSIRAWSERVICE
,GDT_RESERVE_ALL
,
1748 reserve_mode
== 1 ? 1 : 3, 0, 0);
1749 TRACE2(("gdth_search_drives(): RESERVE_ALL code %d\n",
1752 for (i
= 0; i
< MAX_RES_ARGS
; i
+= 4) {
1753 if (reserve_list
[i
] == hanum
&& reserve_list
[i
+1] < ha
->bus_cnt
&&
1754 reserve_list
[i
+2] < ha
->tid_cnt
&& reserve_list
[i
+3] < MAXLUN
) {
1755 TRACE2(("gdth_search_drives(): reserve ha %d bus %d id %d lun %d\n",
1756 reserve_list
[i
], reserve_list
[i
+1],
1757 reserve_list
[i
+2], reserve_list
[i
+3]));
1758 if (!gdth_internal_cmd(hanum
,SCSIRAWSERVICE
,GDT_RESERVE
,0,
1759 reserve_list
[i
+1], reserve_list
[i
+2] |
1760 (reserve_list
[i
+3] << 8))) {
1761 printk("GDT: Error raw service (RESERVE, code %d)\n",
1767 /* scanning for cache devices */
1768 for (i
=0; i
<cdev_cnt
&& i
<MAX_HDRIVES
; ++i
) {
1769 TRACE(("gdth_search_drives() cachedev. %d\n",i
));
1770 if (gdth_internal_cmd(hanum
,CACHESERVICE
,GDT_INFO
,i
,0,0)) {
1771 /* static relation between host drive number and Bus/ID */
1772 TRACE(("gdth_search_dr() drive %d mapped to bus/id %d/%d\n",
1775 ha
->hdr
[i
].present
= TRUE
;
1776 ha
->hdr
[i
].size
= ha
->info
;
1778 /* evaluate mapping (sectors per head, heads per cylinder) */
1779 ha
->hdr
[i
].size
&= ~SECS32
;
1780 if (ha
->info2
== 0) {
1781 gdth_eval_mapping(ha
->hdr
[i
].size
,&drv_cyls
,&drv_hds
,&drv_secs
);
1783 drv_hds
= ha
->info2
& 0xff;
1784 drv_secs
= (ha
->info2
>> 8) & 0xff;
1785 drv_cyls
= ha
->hdr
[i
].size
/drv_hds
/drv_secs
;
1787 ha
->hdr
[i
].heads
= (unchar
)drv_hds
;
1788 ha
->hdr
[i
].secs
= (unchar
)drv_secs
;
1790 ha
->hdr
[i
].size
= drv_cyls
* drv_hds
* drv_secs
;
1791 TRACE2(("gdth_search_dr() cdr. %d size %d hds %d scs %d\n",
1792 i
,ha
->hdr
[i
].size
,drv_hds
,drv_secs
));
1794 /* get informations about device */
1795 if (gdth_internal_cmd(hanum
,CACHESERVICE
,GDT_DEVTYPE
,i
,
1797 TRACE(("gdth_search_dr() cache drive %d devtype %d\n",
1799 ha
->hdr
[i
].devtype
= (ushort
)ha
->info
;
1804 TRACE(("gdth_search_drives() OK\n"));
1809 /* command queueing/sending functions */
1811 static void gdth_putq(int hanum
,Scsi_Cmnd
*scp
,unchar priority
)
1813 register gdth_ha_str
*ha
;
1814 register Scsi_Cmnd
*pscp
;
1815 register Scsi_Cmnd
*nscp
;
1819 TRACE(("gdth_putq() priority %d\n",priority
));
1820 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1821 GDTH_LOCK_HA(ha
, flags
);
1823 scp
->SCp
.this_residual
= (int)priority
;
1824 #if LINUX_VERSION_CODE >= 0x020000
1827 b
= NUMDATA(nscp
->host
)->busnum
;
1830 #if LINUX_VERSION_CODE >= 0x010300
1831 if (priority
>= DEFAULT_PRI
) {
1832 if ((b
!= ha
->virt_bus
&& ha
->raw
[BUS_L2P(ha
,b
)].lock
) ||
1833 (b
== ha
->virt_bus
&& t
< MAX_HDRIVES
&& ha
->hdr
[t
].lock
)) {
1834 TRACE2(("gdth_putq(): locked IO -> update_timeout()\n"));
1835 scp
->SCp
.buffers_residual
= gdth_update_timeout(hanum
, scp
, 0);
1840 if (ha
->req_first
==NULL
) {
1841 ha
->req_first
= scp
; /* queue was empty */
1842 scp
->SCp
.ptr
= NULL
;
1843 } else { /* queue not empty */
1844 pscp
= ha
->req_first
;
1845 nscp
= (Scsi_Cmnd
*)pscp
->SCp
.ptr
;
1846 /* priority: 0-highest,..,0xff-lowest */
1847 while (nscp
&& (unchar
)nscp
->SCp
.this_residual
<= priority
) {
1849 nscp
= (Scsi_Cmnd
*)pscp
->SCp
.ptr
;
1851 pscp
->SCp
.ptr
= (char *)scp
;
1852 scp
->SCp
.ptr
= (char *)nscp
;
1854 GDTH_UNLOCK_HA(ha
, flags
);
1856 #ifdef GDTH_STATISTICS
1858 for (nscp
=ha
->req_first
; nscp
; nscp
=(Scsi_Cmnd
*)nscp
->SCp
.ptr
)
1860 if (max_rq
< flags
) {
1862 TRACE3(("GDT: max_rq = %d\n",(ushort
)max_rq
));
1867 static void gdth_next(int hanum
)
1869 register gdth_ha_str
*ha
;
1870 register Scsi_Cmnd
*pscp
;
1871 register Scsi_Cmnd
*nscp
;
1872 unchar b
, t
, firsttime
;
1873 unchar this_cmd
, next_cmd
;
1877 TRACE(("gdth_next() hanum %d\n",hanum
));
1878 ha
= HADATA(gdth_ctr_tab
[hanum
]);
1879 GDTH_LOCK_HA(ha
, flags
);
1881 ha
->cmd_cnt
= ha
->cmd_offs_dpmem
= 0;
1882 this_cmd
= firsttime
= TRUE
;
1883 next_cmd
= gdth_polling
? FALSE
:TRUE
;
1886 for (nscp
= pscp
= ha
->req_first
; nscp
; nscp
= (Scsi_Cmnd
*)nscp
->SCp
.ptr
) {
1887 if (nscp
!= pscp
&& nscp
!= (Scsi_Cmnd
*)pscp
->SCp
.ptr
)
1888 pscp
= (Scsi_Cmnd
*)pscp
->SCp
.ptr
;
1889 #if LINUX_VERSION_CODE >= 0x020000
1892 b
= NUMDATA(nscp
->host
)->busnum
;
1895 if (nscp
->SCp
.this_residual
>= DEFAULT_PRI
) {
1896 if ((b
!= ha
->virt_bus
&& ha
->raw
[BUS_L2P(ha
,b
)].lock
) ||
1897 (b
== ha
->virt_bus
&& t
< MAX_HDRIVES
&& ha
->hdr
[t
].lock
))
1902 if (gdth_test_busy(hanum
)) { /* controller busy ? */
1903 TRACE(("gdth_next() controller %d busy !\n",hanum
));
1904 if (!gdth_polling
) {
1905 GDTH_UNLOCK_HA(ha
, flags
);
1908 while (gdth_test_busy(hanum
))
1914 #if LINUX_VERSION_CODE >= 0x010300
1915 if (nscp
->done
!= gdth_scsi_done
)
1918 if (nscp
->SCp
.phase
== -1) {
1919 nscp
->SCp
.phase
= SCSIRAWSERVICE
; /* default: raw svc. */
1920 if (nscp
->cmnd
[0] == TEST_UNIT_READY
) {
1921 TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n",
1923 /* TEST_UNIT_READY -> set scan mode */
1924 if ((ha
->scan_mode
& 0x0f) == 0) {
1925 if (b
== 0 && t
== 0 && nscp
->lun
== 0) {
1927 TRACE2(("Scan mode: 0x%x\n", ha
->scan_mode
));
1929 } else if ((ha
->scan_mode
& 0x0f) == 1) {
1930 if (b
== 0 && ((t
== 0 && nscp
->lun
== 1) ||
1931 (t
== 1 && nscp
->lun
== 0))) {
1932 nscp
->SCp
.Status
= GDT_SCAN_START
;
1933 nscp
->SCp
.phase
|= ((ha
->scan_mode
& 0x10 ? 1:0) << 8);
1934 ha
->scan_mode
= 0x12;
1935 TRACE2(("Scan mode: 0x%x (SCAN_START)\n",
1938 ha
->scan_mode
&= 0x10;
1939 TRACE2(("Scan mode: 0x%x\n", ha
->scan_mode
));
1941 } else if (ha
->scan_mode
== 0x12) {
1942 if (b
== ha
->bus_cnt
&& t
== ha
->tid_cnt
-1) {
1943 nscp
->SCp
.Status
= GDT_SCAN_END
;
1944 ha
->scan_mode
&= 0x10;
1945 TRACE2(("Scan mode: 0x%x (SCAN_END)\n",
1953 if (nscp
->SCp
.Status
!= -1) {
1954 if ((nscp
->SCp
.phase
& 0xff) == SCSIRAWSERVICE
) {
1955 if (!(cmd_index
=gdth_fill_raw_cmd(hanum
,nscp
,BUS_L2P(ha
,b
))))
1961 #if LINUX_VERSION_CODE >= 0x010300
1962 if (nscp
->done
== gdth_scsi_done
) {
1963 if (!(cmd_index
=gdth_special_cmd(hanum
,nscp
)))
1968 if (b
!= ha
->virt_bus
) {
1969 if (ha
->raw
[BUS_L2P(ha
,b
)].io_cnt
[t
] >= GDTH_MAX_RAW
||
1970 !(cmd_index
=gdth_fill_raw_cmd(hanum
,nscp
,BUS_L2P(ha
,b
))))
1973 ha
->raw
[BUS_L2P(ha
,b
)].io_cnt
[t
]++;
1974 } else if (t
>= MAX_HDRIVES
|| !ha
->hdr
[t
].present
|| nscp
->lun
!= 0) {
1975 TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n",
1976 nscp
->cmnd
[0], b
, t
, nscp
->lun
));
1977 nscp
->result
= DID_BAD_TARGET
<< 16;
1978 GDTH_UNLOCK_HA(ha
,flags
);
1979 /* io_request_lock already active ! */
1980 nscp
->scsi_done(nscp
);
1981 GDTH_LOCK_HA(ha
,flags
);
1983 switch (nscp
->cmnd
[0]) {
1984 case TEST_UNIT_READY
:
1991 TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp
->cmnd
[0],
1992 nscp
->cmnd
[1],nscp
->cmnd
[2],nscp
->cmnd
[3],
1993 nscp
->cmnd
[4],nscp
->cmnd
[5]));
1994 if (gdth_internal_cache_cmd(hanum
,nscp
)) {
1995 GDTH_UNLOCK_HA(ha
,flags
);
1996 /* io_request_lock already active ! */
1997 nscp
->scsi_done(nscp
);
1998 GDTH_LOCK_HA(ha
,flags
);
2002 case ALLOW_MEDIUM_REMOVAL
:
2003 TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp
->cmnd
[0],
2004 nscp
->cmnd
[1],nscp
->cmnd
[2],nscp
->cmnd
[3],
2005 nscp
->cmnd
[4],nscp
->cmnd
[5]));
2006 if ( (nscp
->cmnd
[4]&1) && !(ha
->hdr
[t
].devtype
&1) ) {
2007 TRACE(("Prevent r. nonremov. drive->do nothing\n"));
2008 nscp
->result
= DID_OK
<< 16;
2009 if (!nscp
->SCp
.have_data_in
)
2010 nscp
->SCp
.have_data_in
++;
2012 GDTH_UNLOCK_HA(ha
,flags
);
2013 /* io_request_lock already active ! */
2014 nscp
->scsi_done(nscp
);
2015 GDTH_LOCK_HA(ha
,flags
);
2018 nscp
->cmnd
[3] = (ha
->hdr
[t
].devtype
&1) ? 1:0;
2019 TRACE(("Prevent/allow r. %d rem. drive %d\n",
2020 nscp
->cmnd
[4],nscp
->cmnd
[3]));
2021 if (!(cmd_index
=gdth_fill_cache_cmd(hanum
,nscp
,t
)))
2030 if (!(cmd_index
=gdth_fill_cache_cmd(hanum
,nscp
,t
)))
2035 TRACE2(("cache cmd %x/%x/%x/%x/%x/%x unknown\n",nscp
->cmnd
[0],
2036 nscp
->cmnd
[1],nscp
->cmnd
[2],nscp
->cmnd
[3],
2037 nscp
->cmnd
[4],nscp
->cmnd
[5]));
2038 printk("GDT: Unknown SCSI command 0x%x to cache service !\n",
2040 nscp
->result
= DID_ABORT
<< 16;
2041 if (!nscp
->SCp
.have_data_in
)
2042 nscp
->SCp
.have_data_in
++;
2044 GDTH_UNLOCK_HA(ha
,flags
);
2045 /* io_request_lock already active ! */
2046 nscp
->scsi_done(nscp
);
2047 GDTH_LOCK_HA(ha
,flags
);
2055 if (nscp
== ha
->req_first
)
2056 ha
->req_first
= pscp
= (Scsi_Cmnd
*)nscp
->SCp
.ptr
;
2058 pscp
->SCp
.ptr
= nscp
->SCp
.ptr
;
2063 if (ha
->cmd_cnt
> 0) {
2064 gdth_release_event(hanum
);
2067 GDTH_UNLOCK_HA(ha
, flags
);
2069 if (gdth_polling
&& ha
->cmd_cnt
> 0) {
2070 if (!gdth_wait(hanum
,cmd_index
,POLL_TIMEOUT
))
2071 printk("GDT: Controller %d: Command %d timed out !\n",
2076 static void gdth_copy_internal_data(Scsi_Cmnd
*scp
,char *buffer
,ushort count
)
2080 struct scatterlist
*sl
;
2082 cpcount
= count
<=(ushort
)scp
->bufflen
? count
:(ushort
)scp
->bufflen
;
2084 sl
= (struct scatterlist
*)scp
->request_buffer
;
2085 for (i
=0,cpsum
=0; i
<scp
->use_sg
; ++i
,++sl
) {
2086 cpnow
= (ushort
)sl
->length
;
2087 TRACE(("copy_internal() now %d sum %d count %d %d\n",
2088 cpnow
,cpsum
,cpcount
,(ushort
)scp
->bufflen
));
2089 if (cpsum
+cpnow
> cpcount
)
2090 cpnow
= cpcount
- cpsum
;
2092 memcpy((char*)sl
->address
,buffer
,cpnow
);
2093 if (cpsum
== cpcount
)
2098 TRACE(("copy_internal() count %d\n",cpcount
));
2099 memcpy((char*)scp
->request_buffer
,buffer
,cpcount
);
2103 static int gdth_internal_cache_cmd(int hanum
,Scsi_Cmnd
*scp
)
2105 register gdth_ha_str
*ha
;
2108 gdth_rdcap_data rdc
;
2110 gdth_modep_data mpd
;
2112 ha
= HADATA(gdth_ctr_tab
[hanum
]);
2114 TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n",
2117 switch (scp
->cmnd
[0]) {
2118 case TEST_UNIT_READY
:
2121 TRACE2(("Test/Verify/Start hdrive %d\n",t
));
2125 TRACE2(("Inquiry hdrive %d devtype %d\n",
2126 t
,ha
->hdr
[t
].devtype
));
2127 inq
.type_qual
= (ha
->hdr
[t
].devtype
&4) ? TYPE_ROM
:TYPE_DISK
;
2128 /* you can here set all disks to removable, if you want to do
2129 a flush using the ALLOW_MEDIUM_REMOVAL command */
2130 inq
.modif_rmb
= ha
->hdr
[t
].devtype
&1 ? 0x80:0x00;
2134 strcpy(inq
.vendor
,"ICP ");
2135 sprintf(inq
.product
,"Host Drive #%02d",t
);
2136 strcpy(inq
.revision
," ");
2137 gdth_copy_internal_data(scp
,(char*)&inq
,sizeof(gdth_inq_data
));
2141 TRACE2(("Request sense hdrive %d\n",t
));
2142 sd
.errorcode
= 0x70;
2147 gdth_copy_internal_data(scp
,(char*)&sd
,sizeof(gdth_sense_data
));
2151 TRACE2(("Mode sense hdrive %d\n",t
));
2152 memset((char*)&mpd
,0,sizeof(gdth_modep_data
));
2153 mpd
.hd
.data_length
= sizeof(gdth_modep_data
);
2154 mpd
.hd
.dev_par
= (ha
->hdr
[t
].devtype
&2) ? 0x80:0;
2155 mpd
.hd
.bd_length
= sizeof(mpd
.bd
);
2156 mpd
.bd
.block_length
[0] = (SECTOR_SIZE
& 0x00ff0000) >> 16;
2157 mpd
.bd
.block_length
[1] = (SECTOR_SIZE
& 0x0000ff00) >> 8;
2158 mpd
.bd
.block_length
[2] = (SECTOR_SIZE
& 0x000000ff);
2159 gdth_copy_internal_data(scp
,(char*)&mpd
,sizeof(gdth_modep_data
));
2163 TRACE2(("Read capacity hdrive %d\n",t
));
2164 rdc
.last_block_no
= ntohl(ha
->hdr
[t
].size
-1);
2165 rdc
.block_length
= ntohl(SECTOR_SIZE
);
2166 gdth_copy_internal_data(scp
,(char*)&rdc
,sizeof(gdth_rdcap_data
));
2170 TRACE2(("Internal cache cmd 0x%x unknown\n",scp
->cmnd
[0]));
2173 scp
->result
= DID_OK
<< 16;
2175 if (!scp
->SCp
.have_data_in
)
2176 scp
->SCp
.have_data_in
++;
2183 static int gdth_fill_cache_cmd(int hanum
,Scsi_Cmnd
*scp
,ushort hdrive
)
2185 register gdth_ha_str
*ha
;
2186 register gdth_cmd_str
*cmdp
;
2187 struct scatterlist
*sl
;
2191 ha
= HADATA(gdth_ctr_tab
[hanum
]);
2193 TRACE(("gdth_fill_cache_cmd() cmd 0x%x cmdsize %d hdrive %d\n",
2194 scp
->cmnd
[0],scp
->cmd_len
,hdrive
));
2196 if (ha
->type
==GDT_EISA
&& ha
->cmd_cnt
>0)
2199 cmdp
->Service
= CACHESERVICE
;
2200 cmdp
->RequestBuffer
= scp
;
2201 /* search free command index */
2202 if (!(cmd_index
=gdth_get_cmd_index(hanum
))) {
2203 TRACE(("GDT: No free command index found\n"));
2206 /* if it's the first command, set command semaphore */
2207 if (ha
->cmd_cnt
== 0)
2208 gdth_set_sema0(hanum
);
2211 if (scp
->cmnd
[0]==ALLOW_MEDIUM_REMOVAL
) {
2212 if (scp
->cmnd
[4] & 1) /* prevent ? */
2213 cmdp
->OpCode
= GDT_MOUNT
;
2214 else if (scp
->cmnd
[3] & 1) /* removable drive ? */
2215 cmdp
->OpCode
= GDT_UNMOUNT
;
2217 cmdp
->OpCode
= GDT_FLUSH
;
2219 if (scp
->cmnd
[0]==WRITE_6
|| scp
->cmnd
[0]==WRITE_10
) {
2220 if (gdth_write_through
)
2221 cmdp
->OpCode
= GDT_WRITE_THR
;
2223 cmdp
->OpCode
= GDT_WRITE
;
2225 cmdp
->OpCode
= GDT_READ
;
2229 cmdp
->BoardNode
= LOCALBOARD
;
2230 cmdp
->u
.cache
.DeviceNo
= hdrive
;
2232 if (scp
->cmnd
[0]==ALLOW_MEDIUM_REMOVAL
) {
2233 cmdp
->u
.cache
.BlockNo
= 1;
2234 cmdp
->u
.cache
.sg_canz
= 0;
2236 if (scp
->cmd_len
!= 6) {
2237 cmdp
->u
.cache
.BlockNo
= ntohl(*(ulong32
*)&scp
->cmnd
[2]);
2238 cmdp
->u
.cache
.BlockCnt
= (ulong32
)ntohs(*(ushort
*)&scp
->cmnd
[7]);
2240 cmdp
->u
.cache
.BlockNo
=
2241 ntohl(*(ulong32
*)&scp
->cmnd
[0]) & 0x001fffffUL
;
2242 cmdp
->u
.cache
.BlockCnt
= scp
->cmnd
[4]==0 ? 0x100 : scp
->cmnd
[4];
2246 cmdp
->u
.cache
.DestAddr
= 0xffffffff;
2247 sl
= (struct scatterlist
*)scp
->request_buffer
;
2248 for (i
=0; i
<scp
->use_sg
; ++i
,++sl
) {
2249 cmdp
->u
.cache
.sg_lst
[i
].sg_ptr
= virt_to_bus(sl
->address
);
2250 cmdp
->u
.cache
.sg_lst
[i
].sg_len
= (ulong32
)sl
->length
;
2252 cmdp
->u
.cache
.sg_canz
= (ulong32
)i
;
2254 #ifdef GDTH_STATISTICS
2255 if (max_sg
< (ulong32
)i
) {
2256 max_sg
= (ulong32
)i
;
2257 TRACE3(("GDT: max_sg = %d\n",i
));
2261 cmdp
->u
.cache
.sg_lst
[i
].sg_len
= 0;
2263 if (ha
->cache_feat
& SCATTER_GATHER
) {
2264 cmdp
->u
.cache
.DestAddr
= 0xffffffff;
2265 cmdp
->u
.cache
.sg_canz
= 1;
2266 cmdp
->u
.cache
.sg_lst
[0].sg_ptr
=
2267 virt_to_bus(scp
->request_buffer
);
2268 cmdp
->u
.cache
.sg_lst
[0].sg_len
= scp
->request_bufflen
;
2269 cmdp
->u
.cache
.sg_lst
[1].sg_len
= 0;
2271 cmdp
->u
.cache
.DestAddr
= virt_to_bus(scp
->request_buffer
);
2272 cmdp
->u
.cache
.sg_canz
= 0;
2276 TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
2277 cmdp
->u
.cache
.DestAddr
,cmdp
->u
.cache
.sg_canz
,
2278 cmdp
->u
.cache
.sg_lst
[0].sg_ptr
,
2279 cmdp
->u
.cache
.sg_lst
[0].sg_len
));
2280 TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n",
2281 cmdp
->OpCode
,cmdp
->u
.cache
.BlockNo
,cmdp
->u
.cache
.BlockCnt
));
2283 /* evaluate command size, check space */
2284 ha
->cmd_len
= GDTOFFSOF(gdth_cmd_str
,u
.cache
.sg_lst
) +
2285 (ushort
)cmdp
->u
.cache
.sg_canz
* sizeof(gdth_sg_str
);
2286 if (ha
->cmd_len
& 3)
2287 ha
->cmd_len
+= (4 - (ha
->cmd_len
& 3));
2289 if (ha
->cmd_cnt
> 0) {
2290 if ((ha
->cmd_offs_dpmem
+ ha
->cmd_len
+ DPMEM_COMMAND_OFFSET
) >
2292 TRACE2(("gdth_fill_cache() DPMEM overflow\n"));
2293 ha
->cmd_tab
[cmd_index
-2].cmnd
= UNUSED_CMND
;
2299 gdth_copy_command(hanum
);
2303 static int gdth_fill_raw_cmd(int hanum
,Scsi_Cmnd
*scp
,unchar b
)
2305 register gdth_ha_str
*ha
;
2306 register gdth_cmd_str
*cmdp
;
2307 struct scatterlist
*sl
;
2312 ha
= HADATA(gdth_ctr_tab
[hanum
]);
2316 TRACE(("gdth_fill_raw_cmd() cmd 0x%x bus %d ID %d LUN %d\n",
2317 scp
->cmnd
[0],b
,t
,l
));
2319 if (ha
->type
==GDT_EISA
&& ha
->cmd_cnt
>0)
2322 cmdp
->Service
= SCSIRAWSERVICE
;
2323 cmdp
->RequestBuffer
= scp
;
2324 /* search free command index */
2325 if (!(cmd_index
=gdth_get_cmd_index(hanum
))) {
2326 TRACE(("GDT: No free command index found\n"));
2329 /* if it's the first command, set command semaphore */
2330 if (ha
->cmd_cnt
== 0)
2331 gdth_set_sema0(hanum
);
2334 if (scp
->SCp
.Status
!= -1) {
2335 cmdp
->OpCode
= scp
->SCp
.Status
; /* special raw cmd. */
2336 cmdp
->BoardNode
= LOCALBOARD
;
2337 cmdp
->u
.raw
.direction
= (scp
->SCp
.phase
>> 8);
2338 TRACE2(("special raw cmd 0x%x param 0x%x\n",
2339 cmdp
->OpCode
, cmdp
->u
.raw
.direction
));
2341 /* evaluate command size */
2342 ha
->cmd_len
= GDTOFFSOF(gdth_cmd_str
,u
.raw
.sg_lst
);
2344 cmdp
->OpCode
= GDT_WRITE
; /* always */
2345 cmdp
->BoardNode
= LOCALBOARD
;
2346 cmdp
->u
.raw
.reserved
= 0;
2347 cmdp
->u
.raw
.mdisc_time
= 0;
2348 cmdp
->u
.raw
.mcon_time
= 0;
2349 cmdp
->u
.raw
.clen
= scp
->cmd_len
;
2350 cmdp
->u
.raw
.target
= t
;
2351 cmdp
->u
.raw
.lun
= l
;
2352 cmdp
->u
.raw
.bus
= b
;
2353 cmdp
->u
.raw
.priority
= 0;
2354 cmdp
->u
.raw
.link_p
= NULL
;
2355 cmdp
->u
.raw
.sdlen
= scp
->request_bufflen
;
2356 cmdp
->u
.raw
.sense_len
= 16;
2357 cmdp
->u
.raw
.sense_data
= virt_to_bus(scp
->sense_buffer
);
2358 cmdp
->u
.raw
.direction
=
2359 gdth_direction_tab
[scp
->cmnd
[0]]==DOU
? DATA_OUT
: DATA_IN
;
2360 memcpy(cmdp
->u
.raw
.cmd
,scp
->cmnd
,12);
2363 cmdp
->u
.raw
.sdata
= 0xffffffff;
2364 sl
= (struct scatterlist
*)scp
->request_buffer
;
2365 for (i
=0; i
<scp
->use_sg
; ++i
,++sl
) {
2366 cmdp
->u
.raw
.sg_lst
[i
].sg_ptr
= virt_to_bus(sl
->address
);
2367 cmdp
->u
.raw
.sg_lst
[i
].sg_len
= (ulong32
)sl
->length
;
2369 cmdp
->u
.raw
.sg_ranz
= (ulong32
)i
;
2371 #ifdef GDTH_STATISTICS
2372 if (max_sg
< (ulong32
)i
) {
2373 max_sg
= (ulong32
)i
;
2374 TRACE3(("GDT: max_sg = %d\n",i
));
2378 cmdp
->u
.raw
.sg_lst
[i
].sg_len
= 0;
2380 if (ha
->raw_feat
& SCATTER_GATHER
) {
2381 cmdp
->u
.raw
.sdata
= 0xffffffff;
2382 cmdp
->u
.raw
.sg_ranz
= 1;
2383 cmdp
->u
.raw
.sg_lst
[0].sg_ptr
= virt_to_bus(scp
->request_buffer
);
2384 cmdp
->u
.raw
.sg_lst
[0].sg_len
= scp
->request_bufflen
;
2385 cmdp
->u
.raw
.sg_lst
[1].sg_len
= 0;
2387 cmdp
->u
.raw
.sdata
= virt_to_bus(scp
->request_buffer
);
2388 cmdp
->u
.raw
.sg_ranz
= 0;
2391 TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
2392 cmdp
->u
.raw
.sdata
,cmdp
->u
.raw
.sg_ranz
,
2393 cmdp
->u
.raw
.sg_lst
[0].sg_ptr
,
2394 cmdp
->u
.raw
.sg_lst
[0].sg_len
));
2396 /* evaluate command size */
2397 ha
->cmd_len
= GDTOFFSOF(gdth_cmd_str
,u
.raw
.sg_lst
) +
2398 (ushort
)cmdp
->u
.raw
.sg_ranz
* sizeof(gdth_sg_str
);
2401 if (ha
->cmd_len
& 3)
2402 ha
->cmd_len
+= (4 - (ha
->cmd_len
& 3));
2404 if (ha
->cmd_cnt
> 0) {
2405 if ((ha
->cmd_offs_dpmem
+ ha
->cmd_len
+ DPMEM_COMMAND_OFFSET
) >
2407 TRACE2(("gdth_fill_raw() DPMEM overflow\n"));
2408 ha
->cmd_tab
[cmd_index
-2].cmnd
= UNUSED_CMND
;
2414 gdth_copy_command(hanum
);
2418 static int gdth_special_cmd(int hanum
,Scsi_Cmnd
*scp
)
2420 register gdth_ha_str
*ha
;
2421 register gdth_cmd_str
*cmdp
;
2424 ha
= HADATA(gdth_ctr_tab
[hanum
]);
2426 TRACE2(("gdth_special_cmd(): "));
2428 if (ha
->type
==GDT_EISA
&& ha
->cmd_cnt
>0)
2431 memcpy( cmdp
, scp
->request_buffer
, sizeof(gdth_cmd_str
));
2432 cmdp
->RequestBuffer
= scp
;
2434 /* search free command index */
2435 if (!(cmd_index
=gdth_get_cmd_index(hanum
))) {
2436 TRACE(("GDT: No free command index found\n"));
2440 /* if it's the first command, set command semaphore */
2441 if (ha
->cmd_cnt
== 0)
2442 gdth_set_sema0(hanum
);
2444 /* evaluate command size, check space */
2445 if (cmdp
->OpCode
== GDT_IOCTL
) {
2446 TRACE2(("IOCTL\n"));
2448 GDTOFFSOF(gdth_cmd_str
,u
.ioctl
.p_param
) + sizeof(ulong32
);
2449 } else if (cmdp
->Service
== CACHESERVICE
) {
2450 TRACE2(("cache command %d\n",cmdp
->OpCode
));
2452 GDTOFFSOF(gdth_cmd_str
,u
.cache
.sg_lst
) + sizeof(gdth_sg_str
);
2453 } else if (cmdp
->Service
== SCSIRAWSERVICE
) {
2454 TRACE2(("raw command %d/%d\n",cmdp
->OpCode
,cmdp
->u
.raw
.cmd
[0]));
2456 GDTOFFSOF(gdth_cmd_str
,u
.raw
.sg_lst
) + sizeof(gdth_sg_str
);
2459 if (ha
->cmd_len
& 3)
2460 ha
->cmd_len
+= (4 - (ha
->cmd_len
& 3));
2462 if (ha
->cmd_cnt
> 0) {
2463 if ((ha
->cmd_offs_dpmem
+ ha
->cmd_len
+ DPMEM_COMMAND_OFFSET
) >
2465 TRACE2(("gdth_special_cmd() DPMEM overflow\n"));
2466 ha
->cmd_tab
[cmd_index
-2].cmnd
= UNUSED_CMND
;
2472 gdth_copy_command(hanum
);
2477 /* Controller event handling functions */
2478 static gdth_evt_str
*gdth_store_event(gdth_ha_str
*ha
, ushort source
,
2479 ushort idx
, gdth_evt_data
*evt
)
2484 /* no GDTH_LOCK_HA() ! */
2485 TRACE2(("gdth_store_event() source %d idx %d\n", source
, idx
));
2486 if (source
== 0) /* no source -> no event */
2489 if (ebuffer
[elastidx
].event_source
== source
&&
2490 ebuffer
[elastidx
].event_idx
== idx
&&
2491 !memcmp((char *)&ebuffer
[elastidx
].event_data
.eu
,
2492 (char *)&evt
->eu
, evt
->size
)) {
2493 e
= &ebuffer
[elastidx
];
2494 do_gettimeofday(&tv
);
2495 e
->last_stamp
= tv
.tv_sec
;
2498 if (ebuffer
[elastidx
].event_source
!= 0) { /* entry not free ? */
2500 if (elastidx
== MAX_EVENTS
)
2502 if (elastidx
== eoldidx
) { /* reached mark ? */
2504 if (eoldidx
== MAX_EVENTS
)
2508 e
= &ebuffer
[elastidx
];
2509 e
->event_source
= source
;
2511 do_gettimeofday(&tv
);
2512 e
->first_stamp
= e
->last_stamp
= tv
.tv_sec
;
2514 e
->event_data
= *evt
;
2519 static int gdth_read_event(gdth_ha_str
*ha
, int handle
, gdth_evt_str
*estr
)
2525 TRACE2(("gdth_read_event() handle %d\n", handle
));
2526 GDTH_LOCK_HA(ha
, flags
);
2531 estr
->event_source
= 0;
2533 if (eindex
>= MAX_EVENTS
) {
2534 GDTH_UNLOCK_HA(ha
, flags
);
2537 e
= &ebuffer
[eindex
];
2538 if (e
->event_source
!= 0) {
2539 if (eindex
!= elastidx
) {
2540 if (++eindex
== MAX_EVENTS
)
2545 memcpy(estr
, e
, sizeof(gdth_evt_str
));
2547 GDTH_UNLOCK_HA(ha
, flags
);
2551 static void gdth_readapp_event(gdth_ha_str
*ha
,
2552 unchar application
, gdth_evt_str
*estr
)
2557 unchar found
= FALSE
;
2559 TRACE2(("gdth_readapp_event() app. %d\n", application
));
2560 GDTH_LOCK_HA(ha
, flags
);
2563 e
= &ebuffer
[eindex
];
2564 if (e
->event_source
== 0)
2566 if ((e
->application
& application
) == 0) {
2567 e
->application
|= application
;
2571 if (eindex
== elastidx
)
2573 if (++eindex
== MAX_EVENTS
)
2577 memcpy(estr
, e
, sizeof(gdth_evt_str
));
2579 estr
->event_source
= 0;
2580 GDTH_UNLOCK_HA(ha
, flags
);
2583 static void gdth_clear_events()
2585 TRACE(("gdth_clear_events()"));
2587 eoldidx
= elastidx
= 0;
2588 ebuffer
[0].event_source
= 0;
2592 /* SCSI interface functions */
2594 #if LINUX_VERSION_CODE >= 0x010346
2595 static void gdth_interrupt(int irq
,void *dev_id
,struct pt_regs
*regs
)
2597 static void gdth_interrupt(int irq
,struct pt_regs
*regs
)
2600 register gdth_ha_str
*ha
;
2601 gdt6m_dpram_str
*dp6m_ptr
;
2602 gdt6_dpram_str
*dp6_ptr
;
2603 gdt2_dpram_str
*dp2_ptr
;
2607 ushort CmdStatus
, Service
= 0;
2608 ulong32 InfoBytes
, InfoBytes2
= 0;
2612 TRACE(("gdth_interrupt() IRQ %d\n",irq
));
2614 /* if polling and not from gdth_wait() -> return */
2616 if (!gdth_from_wait
) {
2622 GDTH_LOCK_HA((gdth_ha_str
*)dev_id
,flags
);
2625 /* search controller */
2626 if ((hanum
= gdth_get_status(&IStatus
,irq
)) == -1) {
2628 TRACE2(("gdth_interrupt(): Spurious interrupt received\n"));
2631 GDTH_UNLOCK_HA((gdth_ha_str
*)dev_id
,flags
);
2635 #ifdef GDTH_STATISTICS
2639 ha
= HADATA(gdth_ctr_tab
[hanum
]);
2640 if (ha
->type
== GDT_EISA
) {
2641 if (IStatus
& 0x80) { /* error flag */
2643 CmdStatus
= inw(ha
->bmic
+ MAILBOXREG
+8);
2644 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus
,CmdStatus
));
2645 if (IStatus
== ASYNCINDEX
) { /* async. event ? */
2646 Service
= inw(ha
->bmic
+ MAILBOXREG
+10);
2647 InfoBytes2
= inl(ha
->bmic
+ MAILBOXREG
+4);
2649 } else /* no error */
2651 InfoBytes
= inl(ha
->bmic
+ MAILBOXREG
+12);
2652 if (gdth_polling
) /* init. -> more info */
2653 InfoBytes2
= inl(ha
->bmic
+ MAILBOXREG
+4);
2654 outb(0xff, ha
->bmic
+ EDOORREG
); /* acknowledge interrupt */
2655 outb(0x00, ha
->bmic
+ SEMA1REG
); /* reset status semaphore */
2656 } else if (ha
->type
== GDT_ISA
) {
2657 dp2_ptr
= (gdt2_dpram_str
*)ha
->brd
;
2658 if (IStatus
& 0x80) { /* error flag */
2660 CmdStatus
= gdth_readw(&dp2_ptr
->u
.ic
.Status
);
2661 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus
,CmdStatus
));
2662 if (IStatus
== ASYNCINDEX
) { /* async. event ? */
2663 Service
= gdth_readw(&dp2_ptr
->u
.ic
.Service
);
2664 InfoBytes2
= gdth_readl(&dp2_ptr
->u
.ic
.Info
[1]);
2666 } else /* no error */
2668 InfoBytes
= gdth_readl(&dp2_ptr
->u
.ic
.Info
[0]);
2669 if (gdth_polling
) /* init. -> more info */
2670 InfoBytes2
= gdth_readl(&dp2_ptr
->u
.ic
.Info
[1]);
2671 gdth_writeb(0xff, &dp2_ptr
->io
.irqdel
); /* acknowledge interrupt */
2672 gdth_writeb(0, &dp2_ptr
->u
.ic
.Cmd_Index
); /* reset command index */
2673 gdth_writeb(0, &dp2_ptr
->io
.Sema1
); /* reset status semaphore */
2674 } else if (ha
->type
== GDT_PCI
) {
2675 dp6_ptr
= (gdt6_dpram_str
*)ha
->brd
;
2676 if (IStatus
& 0x80) { /* error flag */
2678 CmdStatus
= gdth_readw(&dp6_ptr
->u
.ic
.Status
);
2679 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus
,CmdStatus
));
2680 if (IStatus
== ASYNCINDEX
) { /* async. event ? */
2681 Service
= gdth_readw(&dp6_ptr
->u
.ic
.Service
);
2682 InfoBytes2
= gdth_readl(&dp6_ptr
->u
.ic
.Info
[1]);
2684 } else /* no error */
2686 InfoBytes
= gdth_readl(&dp6_ptr
->u
.ic
.Info
[0]);
2687 if (gdth_polling
) /* init. -> more info */
2688 InfoBytes2
= gdth_readl(&dp6_ptr
->u
.ic
.Info
[1]);
2689 gdth_writeb(0xff, &dp6_ptr
->io
.irqdel
); /* acknowledge interrupt */
2690 gdth_writeb(0, &dp6_ptr
->u
.ic
.Cmd_Index
); /* reset command index */
2691 gdth_writeb(0, &dp6_ptr
->io
.Sema1
); /* reset status semaphore */
2692 } else if (ha
->type
== GDT_PCINEW
) {
2693 if (IStatus
& 0x80) { /* error flag */
2695 CmdStatus
= inw(PTR2USHORT(&ha
->plx
->status
));
2696 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus
,CmdStatus
));
2697 if (IStatus
== ASYNCINDEX
) { /* async. event ? */
2698 Service
= inw(PTR2USHORT(&ha
->plx
->service
));
2699 InfoBytes2
= inl(PTR2USHORT(&ha
->plx
->info
[1]));
2704 InfoBytes
= inl(PTR2USHORT(&ha
->plx
->info
[0]));
2705 if (gdth_polling
) /* init. -> more info */
2706 InfoBytes2
= inl(PTR2USHORT(&ha
->plx
->info
[1]));
2707 outb(0xff, PTR2USHORT(&ha
->plx
->edoor_reg
));
2708 outb(0x00, PTR2USHORT(&ha
->plx
->sema1_reg
));
2709 } else if (ha
->type
== GDT_PCIMPR
) {
2710 dp6m_ptr
= (gdt6m_dpram_str
*)ha
->brd
;
2711 if (IStatus
& 0x80) { /* error flag */
2713 CmdStatus
= gdth_readw(&dp6m_ptr
->i960r
.status
);
2714 TRACE2(("gdth_interrupt() error %d/%d\n",IStatus
,CmdStatus
));
2715 if (IStatus
== ASYNCINDEX
) { /* async. event ? */
2716 Service
= gdth_readw(&dp6m_ptr
->i960r
.service
);
2717 InfoBytes2
= gdth_readl(&dp6m_ptr
->i960r
.info
[1]);
2719 } else /* no error */
2721 InfoBytes
= gdth_readl(&dp6m_ptr
->i960r
.info
[0]);
2722 if (gdth_polling
) /* init. -> more info */
2723 InfoBytes2
= gdth_readl(&dp6m_ptr
->i960r
.info
[1]);
2724 gdth_writeb(0xff, &dp6m_ptr
->i960r
.edoor_reg
);
2725 gdth_writeb(0, &dp6m_ptr
->i960r
.sema1_reg
);
2727 TRACE2(("gdth_interrupt() unknown controller type\n"));
2729 GDTH_UNLOCK_HA((gdth_ha_str
*)dev_id
,flags
);
2733 TRACE(("gdth_interrupt() index %d stat %d info %d\n",
2734 IStatus
,CmdStatus
,InfoBytes
));
2735 ha
->status
= CmdStatus
;
2736 ha
->info
= InfoBytes
;
2737 ha
->info2
= InfoBytes2
;
2739 if (gdth_from_wait
) {
2741 wait_index
= (int)IStatus
;
2744 if (IStatus
== ASYNCINDEX
) {
2745 TRACE2(("gdth_interrupt() async. event\n"));
2746 gdth_async_event(hanum
,Service
);
2748 GDTH_UNLOCK_HA((gdth_ha_str
*)dev_id
,flags
);
2753 if (IStatus
== SPEZINDEX
) {
2754 TRACE2(("Service unknown or not initialized !\n"));
2755 dvr
.size
= sizeof(dvr
.eu
.driver
);
2756 dvr
.eu
.driver
.ionode
= hanum
;
2757 gdth_store_event(ha
, ES_DRIVER
, 4, &dvr
);
2759 GDTH_UNLOCK_HA((gdth_ha_str
*)dev_id
,flags
);
2762 scp
= ha
->cmd_tab
[IStatus
-2].cmnd
;
2763 Service
= ha
->cmd_tab
[IStatus
-2].service
;
2764 ha
->cmd_tab
[IStatus
-2].cmnd
= UNUSED_CMND
;
2765 if (scp
== UNUSED_CMND
) {
2766 TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus
));
2767 dvr
.size
= sizeof(dvr
.eu
.driver
);
2768 dvr
.eu
.driver
.ionode
= hanum
;
2769 dvr
.eu
.driver
.index
= IStatus
;
2770 gdth_store_event(ha
, ES_DRIVER
, 1, &dvr
);
2772 GDTH_UNLOCK_HA((gdth_ha_str
*)dev_id
,flags
);
2775 if (scp
== INTERNAL_CMND
) {
2776 TRACE(("gdth_interrupt() answer to internal command\n"));
2778 GDTH_UNLOCK_HA((gdth_ha_str
*)dev_id
,flags
);
2782 TRACE(("gdth_interrupt() sync. status\n"));
2783 rval
= gdth_sync_event(hanum
,Service
,IStatus
,scp
);
2785 GDTH_UNLOCK_HA((gdth_ha_str
*)dev_id
,flags
);
2787 gdth_putq(hanum
,scp
,scp
->SCp
.this_residual
);
2788 } else if (rval
== 1) {
2789 GDTH_LOCK_SCSI_DONE(flags
);
2790 scp
->scsi_done(scp
);
2791 GDTH_UNLOCK_SCSI_DONE(flags
);
2796 static int gdth_sync_event(int hanum
,int service
,unchar index
,Scsi_Cmnd
*scp
)
2798 register gdth_ha_str
*ha
;
2805 ha
= HADATA(gdth_ctr_tab
[hanum
]);
2807 TRACE(("gdth_sync_event() serv %d status %d\n",
2808 service
,ha
->status
));
2810 if (service
== SCREENSERVICE
) {
2811 msg
= (gdth_msg_str
*)ha
->pscratch
;
2812 ha
->scratch_busy
= FALSE
;
2813 TRACE(("len: %d, answer: %d, ext: %d, alen: %d\n",
2814 msg
->msg_len
,msg
->msg_answer
,msg
->msg_ext
,msg
->msg_alen
));
2816 if (!(msg
->msg_answer
&& msg
->msg_ext
)) {
2817 msg
->msg_text
[msg
->msg_len
] = '\0';
2818 printk("%s",msg
->msg_text
);
2821 if (msg
->msg_ext
&& !msg
->msg_answer
) {
2822 while (gdth_test_busy(hanum
))
2824 cmdp
->Service
= SCREENSERVICE
;
2825 cmdp
->RequestBuffer
= SCREEN_CMND
;
2826 gdth_get_cmd_index(hanum
);
2827 gdth_set_sema0(hanum
);
2828 cmdp
->OpCode
= GDT_READ
;
2829 cmdp
->BoardNode
= LOCALBOARD
;
2830 cmdp
->u
.screen
.reserved
= 0;
2831 cmdp
->u
.screen
.msg_handle
= msg
->msg_handle
;
2832 cmdp
->u
.screen
.msg_addr
= virt_to_bus(msg
);
2833 ha
->scratch_busy
= TRUE
;
2834 ha
->cmd_offs_dpmem
= 0;
2835 ha
->cmd_len
= GDTOFFSOF(gdth_cmd_str
,u
.screen
.msg_addr
)
2838 gdth_copy_command(hanum
);
2839 gdth_release_event(hanum
);
2843 if (msg
->msg_answer
&& msg
->msg_alen
) {
2844 for (i
=0; i
<msg
->msg_alen
&& i
<MSGLEN
; ++i
) {
2849 msg
->msg_text
[i
] = c
;
2852 if (c
!='\r' && msg
->msg_alen
!=0) {
2853 msg
->msg_answer
= 1;
2857 msg
->msg_answer
= 0;
2860 while (gdth_test_busy(hanum
))
2862 cmdp
->Service
= SCREENSERVICE
;
2863 cmdp
->RequestBuffer
= SCREEN_CMND
;
2864 gdth_get_cmd_index(hanum
);
2865 gdth_set_sema0(hanum
);
2866 cmdp
->OpCode
= GDT_WRITE
;
2867 cmdp
->BoardNode
= LOCALBOARD
;
2868 cmdp
->u
.screen
.reserved
= 0;
2869 cmdp
->u
.screen
.msg_handle
= msg
->msg_handle
;
2870 cmdp
->u
.screen
.msg_addr
= virt_to_bus(msg
);
2871 ha
->scratch_busy
= TRUE
;
2872 ha
->cmd_offs_dpmem
= 0;
2873 ha
->cmd_len
= GDTOFFSOF(gdth_cmd_str
,u
.screen
.msg_addr
)
2876 gdth_copy_command(hanum
);
2877 gdth_release_event(hanum
);
2883 if (scp
->SCp
.Status
== -1 && scp
->channel
!= ha
->virt_bus
) {
2884 ha
->raw
[BUS_L2P(ha
,scp
->channel
)].io_cnt
[scp
->target
]--;
2886 /* cache or raw service */
2887 if (ha
->status
== S_OK
) {
2888 scp
->SCp
.Message
= S_OK
;
2889 if (scp
->SCp
.Status
!= -1) {
2890 TRACE2(("gdth_sync_event(): special cmd 0x%x OK\n",
2892 scp
->SCp
.Status
= -1;
2893 scp
->SCp
.this_residual
= HIGH_PRI
;
2896 scp
->result
= DID_OK
<< 16;
2897 } else if (ha
->status
== S_BSY
) {
2898 TRACE2(("Controller busy -> retry !\n"));
2899 scp
->SCp
.Message
= S_BSY
;
2902 scp
->SCp
.Message
= (int)((ha
->info
<<16)|ha
->status
);
2903 if (scp
->SCp
.Status
!= -1) {
2904 TRACE2(("gdth_sync_event(): special cmd 0x%x error 0x%x\n",
2905 scp
->SCp
.Status
, ha
->status
));
2906 scp
->SCp
.Status
= -1;
2907 scp
->SCp
.this_residual
= HIGH_PRI
;
2910 if (service
== CACHESERVICE
) {
2911 memset((char*)scp
->sense_buffer
,0,16);
2912 scp
->sense_buffer
[0] = 0x70;
2913 scp
->sense_buffer
[2] = NOT_READY
;
2914 scp
->result
= (DID_OK
<< 16) | (CHECK_CONDITION
<< 1);
2916 #if LINUX_VERSION_CODE >= 0x010300
2917 if (scp
->done
!= gdth_scsi_done
)
2920 dvr
.size
= sizeof(dvr
.eu
.sync
);
2921 dvr
.eu
.sync
.ionode
= hanum
;
2922 dvr
.eu
.sync
.service
= service
;
2923 dvr
.eu
.sync
.status
= ha
->status
;
2924 dvr
.eu
.sync
.info
= ha
->info
;
2925 dvr
.eu
.sync
.hostdrive
= scp
->target
;
2926 if (ha
->status
>= 0x8000)
2927 gdth_store_event(ha
, ES_SYNC
, 0, &dvr
);
2929 gdth_store_event(ha
, ES_SYNC
, service
, &dvr
);
2932 if (ha
->status
!=S_RAW_SCSI
|| ha
->info
>=0x100) {
2933 scp
->result
= DID_BAD_TARGET
<< 16;
2935 scp
->result
= (DID_OK
<< 16) | ha
->info
;
2939 if (!scp
->SCp
.have_data_in
)
2940 scp
->SCp
.have_data_in
++;
2948 static char *async_cache_tab
[] = {
2949 /* 0*/ "\011\000\002\002\002\004\002\006\004"
2950 "GDT HA %u, service %u, async. status %u/%lu unknown",
2951 /* 1*/ "\011\000\002\002\002\004\002\006\004"
2952 "GDT HA %u, service %u, async. status %u/%lu unknown",
2953 /* 2*/ "\005\000\002\006\004"
2954 "GDT HA %u, Host Drive %lu not ready",
2955 /* 3*/ "\005\000\002\006\004"
2956 "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",
2957 /* 4*/ "\005\000\002\006\004"
2958 "GDT HA %u, mirror update on Host Drive %lu failed",
2959 /* 5*/ "\005\000\002\006\004"
2960 "GDT HA %u, Mirror Drive %lu failed",
2961 /* 6*/ "\005\000\002\006\004"
2962 "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",
2963 /* 7*/ "\005\000\002\006\004"
2964 "GDT HA %u, Host Drive %lu write protected",
2965 /* 8*/ "\005\000\002\006\004"
2966 "GDT HA %u, media changed in Host Drive %lu",
2967 /* 9*/ "\005\000\002\006\004"
2968 "GDT HA %u, Host Drive %lu is offline",
2969 /*10*/ "\005\000\002\006\004"
2970 "GDT HA %u, media change of Mirror Drive %lu",
2971 /*11*/ "\005\000\002\006\004"
2972 "GDT HA %u, Mirror Drive %lu is write protected",
2973 /*12*/ "\005\000\002\006\004"
2974 "GDT HA %u, general error on Host Drive %lu. Please check the devices of this drive!",
2975 /*13*/ "\007\000\002\006\002\010\002"
2976 "GDT HA %u, Array Drive %u: Cache Drive %u failed",
2977 /*14*/ "\005\000\002\006\002"
2978 "GDT HA %u, Array Drive %u: FAIL state entered",
2979 /*15*/ "\005\000\002\006\002"
2980 "GDT HA %u, Array Drive %u: error",
2981 /*16*/ "\007\000\002\006\002\010\002"
2982 "GDT HA %u, Array Drive %u: failed drive replaced by Cache Drive %u",
2983 /*17*/ "\005\000\002\006\002"
2984 "GDT HA %u, Array Drive %u: parity build failed",
2985 /*18*/ "\005\000\002\006\002"
2986 "GDT HA %u, Array Drive %u: drive rebuild failed",
2987 /*19*/ "\005\000\002\010\002"
2988 "GDT HA %u, Test of Hot Fix %u failed",
2989 /*20*/ "\005\000\002\006\002"
2990 "GDT HA %u, Array Drive %u: drive build finished successfully",
2991 /*21*/ "\005\000\002\006\002"
2992 "GDT HA %u, Array Drive %u: drive rebuild finished successfully",
2993 /*22*/ "\007\000\002\006\002\010\002"
2994 "GDT HA %u, Array Drive %u: Hot Fix %u activated",
2995 /*23*/ "\005\000\002\006\002"
2996 "GDT HA %u, Host Drive %u: processing of i/o aborted due to serious drive error",
2997 /*24*/ "\005\000\002\010\002"
2998 "GDT HA %u, mirror update on Cache Drive %u completed",
2999 /*25*/ "\005\000\002\010\002"
3000 "GDT HA %u, mirror update on Cache Drive %lu failed",
3001 /*26*/ "\005\000\002\006\002"
3002 "GDT HA %u, Array Drive %u: drive rebuild started",
3003 /*27*/ "\005\000\002\012\001"
3004 "GDT HA %u, Fault bus %u: SHELF OK detected",
3005 /*28*/ "\005\000\002\012\001"
3006 "GDT HA %u, Fault bus %u: SHELF not OK detected",
3007 /*29*/ "\007\000\002\012\001\013\001"
3008 "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug started",
3009 /*30*/ "\007\000\002\012\001\013\001"
3010 "GDT HA %u, Fault bus %u, ID %u: new disk detected",
3011 /*31*/ "\007\000\002\012\001\013\001"
3012 "GDT HA %u, Fault bus %u, ID %u: old disk detected",
3013 /*32*/ "\007\000\002\012\001\013\001"
3014 "GDT HA %u, Fault bus %u, ID %u: plugging an active disk is illegal",
3015 /*33*/ "\007\000\002\012\001\013\001"
3016 "GDT HA %u, Fault bus %u, ID %u: illegal device detected",
3017 /*34*/ "\011\000\002\012\001\013\001\006\004"
3018 "GDT HA %u, Fault bus %u, ID %u: insufficient disk capacity (%lu MB required)",
3019 /*35*/ "\007\000\002\012\001\013\001"
3020 "GDT HA %u, Fault bus %u, ID %u: disk write protected",
3021 /*36*/ "\007\000\002\012\001\013\001"
3022 "GDT HA %u, Fault bus %u, ID %u: disk not available",
3023 /*37*/ "\007\000\002\012\001\006\004"
3024 "GDT HA %u, Fault bus %u: swap detected (%lu)",
3025 /*38*/ "\007\000\002\012\001\013\001"
3026 "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug finished successfully",
3027 /*39*/ "\007\000\002\012\001\013\001"
3028 "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug aborted due to user Hot Plug",
3029 /*40*/ "\007\000\002\012\001\013\001"
3030 "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug aborted",
3031 /*41*/ "\007\000\002\012\001\013\001"
3032 "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug for Hot Fix started",
3033 /*42*/ "\005\000\002\006\002"
3034 "GDT HA %u, Array Drive %u: drive build started",
3035 /*43*/ "\003\000\002"
3036 "GDT HA %u, DRAM parity error detected",
3037 /*44*/ "\005\000\002\006\002"
3038 "GDT HA %u, Mirror Drive %u: update started",
3039 /*45*/ "\007\000\002\006\002\010\002"
3040 "GDT HA %u, Mirror Drive %u: Hot Fix %u activated",
3041 /*46*/ "\005\000\002\006\002"
3042 "GDT HA %u, Array Drive %u: no matching Pool Hot Fix Drive available",
3043 /*47*/ "\005\000\002\006\002"
3044 "GDT HA %u, Array Drive %u: Pool Hot Fix Drive available",
3045 /*48*/ "\005\000\002\006\002"
3046 "GDT HA %u, Mirror Drive %u: no matching Pool Hot Fix Drive available",
3047 /*49*/ "\005\000\002\006\002"
3048 "GDT HA %u, Mirror Drive %u: Pool Hot Fix Drive available",
3049 /*50*/ "\007\000\002\012\001\013\001"
3050 "GDT HA %u, SCSI bus %u, ID %u: IGNORE_WIDE_RESIDUE message received",
3051 /*51*/ "\005\000\002\006\002"
3052 "GDT HA %u, Array Drive %u: expand started",
3053 /*52*/ "\005\000\002\006\002"
3054 "GDT HA %u, Array Drive %u: expand finished successfully",
3055 /*53*/ "\005\000\002\006\002"
3056 "GDT HA %u, Array Drive %u: expand failed",
3057 /*54*/ "\003\000\002"
3058 "GDT HA %u, CPU temperature critical",
3059 /*55*/ "\003\000\002"
3060 "GDT HA %u, CPU temperature OK",
3061 /*56*/ "\005\000\002\006\004"
3062 "GDT HA %u, Host drive %lu created",
3063 /*57*/ "\005\000\002\006\002"
3064 "GDT HA %u, Array Drive %u: expand restarted",
3065 /*58*/ "\005\000\002\006\002"
3066 "GDT HA %u, Array Drive %u: expand stopped",
3067 /*59*/ "\005\000\002\010\002"
3068 "GDT HA %u, Mirror Drive %u: drive build quited",
3069 /*60*/ "\005\000\002\006\002"
3070 "GDT HA %u, Array Drive %u: parity build quited",
3071 /*61*/ "\005\000\002\006\002"
3072 "GDT HA %u, Array Drive %u: drive rebuild quited",
3073 /*62*/ "\005\000\002\006\002"
3074 "GDT HA %u, Array Drive %u: parity verify started",
3075 /*63*/ "\005\000\002\006\002"
3076 "GDT HA %u, Array Drive %u: parity verify done",
3077 /*64*/ "\005\000\002\006\002"
3078 "GDT HA %u, Array Drive %u: parity verify failed",
3079 /*65*/ "\005\000\002\006\002"
3080 "GDT HA %u, Array Drive %u: parity error detected",
3081 /*66*/ "\005\000\002\006\002"
3082 "GDT HA %u, Array Drive %u: parity verify quited",
3083 /*67*/ "\005\000\002\006\002"
3084 "GDT HA %u, Host Drive %u reserved",
3085 /*68*/ "\005\000\002\006\002"
3086 "GDT HA %u, Host Drive %u mounted and released",
3087 /*69*/ "\005\000\002\006\002"
3088 "GDT HA %u, Host Drive %u released",
3089 /*70*/ "\003\000\002"
3090 "GDT HA %u, DRAM error detected and corrected with ECC",
3091 /*71*/ "\003\000\002"
3092 "GDT HA %u, Uncorrectable DRAM error detected with ECC",
3093 /*72*/ "\011\000\002\012\001\013\001\014\001"
3094 "GDT HA %u, SCSI bus %u, ID %u, LUN %u: reassigning block",
3098 static int gdth_async_event(int hanum
,int service
)
3106 ha
= HADATA(gdth_ctr_tab
[hanum
]);
3108 msg
= (gdth_msg_str
*)ha
->pscratch
;
3109 TRACE2(("gdth_async_event() ha %d serv %d\n",
3112 if (service
== SCREENSERVICE
) {
3113 if (ha
->status
== MSG_REQUEST
) {
3114 while (gdth_test_busy(hanum
))
3116 cmdp
->Service
= SCREENSERVICE
;
3117 cmdp
->RequestBuffer
= SCREEN_CMND
;
3118 cmd_index
= gdth_get_cmd_index(hanum
);
3119 gdth_set_sema0(hanum
);
3120 cmdp
->OpCode
= GDT_READ
;
3121 cmdp
->BoardNode
= LOCALBOARD
;
3122 cmdp
->u
.screen
.reserved
= 0;
3123 cmdp
->u
.screen
.msg_handle
= MSG_INV_HANDLE
;
3124 cmdp
->u
.screen
.msg_addr
= virt_to_bus(msg
);
3125 ha
->scratch_busy
= TRUE
;
3126 ha
->cmd_offs_dpmem
= 0;
3127 ha
->cmd_len
= GDTOFFSOF(gdth_cmd_str
,u
.screen
.msg_addr
)
3130 gdth_copy_command(hanum
);
3131 if (ha
->type
== GDT_EISA
)
3132 printk("[EISA slot %d] ",(ushort
)ha
->brd_phys
);
3133 else if (ha
->type
== GDT_ISA
)
3134 printk("[DPMEM 0x%4X] ",(ushort
)ha
->brd_phys
);
3136 printk("[PCI %d/%d] ",(ushort
)(ha
->brd_phys
>>8),
3137 (ushort
)((ha
->brd_phys
>>3)&0x1f));
3138 gdth_release_event(hanum
);
3142 dvr
.size
= sizeof(dvr
.eu
.async
);
3143 dvr
.eu
.async
.ionode
= hanum
;
3144 dvr
.eu
.async
.service
= service
;
3145 dvr
.eu
.async
.status
= ha
->status
;
3146 dvr
.eu
.async
.info
= ha
->info
;
3147 *(ulong32
*)dvr
.eu
.async
.scsi_coord
= ha
->info2
;
3148 gdth_store_event(ha
, ES_ASYNC
, service
, &dvr
);
3149 gdth_log_event( &dvr
, NULL
);
3154 static void gdth_log_event(gdth_evt_data
*dvr
, char *buffer
)
3156 gdth_stackframe stack
;
3160 TRACE2(("gdth_log_event()\n"));
3161 if (dvr
->eu
.async
.service
== CACHESERVICE
&&
3162 INDEX_OK(dvr
->eu
.async
.status
, async_cache_tab
)) {
3163 TRACE2(("GDT: Async. event cache service, event no.: %d\n",
3164 dvr
->eu
.async
.status
));
3166 f
= async_cache_tab
[dvr
->eu
.async
.status
];
3168 /* i: parameter to push, j: stack element to fill */
3169 for (j
=0,i
=1; i
< f
[0]; i
+=2) {
3172 stack
.b
[j
++] = *(ulong32
*)&dvr
->eu
.stream
[(int)f
[i
]];
3175 stack
.b
[j
++] = *(ushort
*)&dvr
->eu
.stream
[(int)f
[i
]];
3178 stack
.b
[j
++] = *(unchar
*)&dvr
->eu
.stream
[(int)f
[i
]];
3185 if (buffer
== NULL
) {
3186 printk(&f
[(int)f
[0]],stack
);
3189 sprintf(buffer
,&f
[(int)f
[0]],stack
);
3193 if (buffer
== NULL
) {
3194 printk("GDT HA %u, Unknown async. event service %d event no. %d\n",
3195 dvr
->eu
.async
.ionode
,dvr
->eu
.async
.service
,dvr
->eu
.async
.status
);
3197 sprintf(buffer
,"GDT HA %u, Unknown async. event service %d event no. %d",
3198 dvr
->eu
.async
.ionode
,dvr
->eu
.async
.service
,dvr
->eu
.async
.status
);
3203 #ifdef GDTH_STATISTICS
3204 void gdth_timeout(ulong data
)
3212 ha
= HADATA(gdth_ctr_tab
[hanum
]);
3213 GDTH_LOCK_HA(ha
, flags
);
3215 for (act_stats
=0,i
=0; i
<GDTH_MAXCMDS
; ++i
)
3216 if (ha
->cmd_tab
[i
].cmnd
!= UNUSED_CMND
)
3219 for (act_rq
=0,nscp
=ha
->req_first
; nscp
; nscp
=(Scsi_Cmnd
*)nscp
->SCp
.ptr
)
3222 TRACE2(("gdth_to(): ints %d, ios %d, act_stats %d, act_rq %d\n",
3223 act_ints
, act_ios
, act_stats
, act_rq
));
3224 act_ints
= act_ios
= 0;
3226 gdth_timer
.expires
= jiffies
+ 30 * HZ
;
3227 add_timer(&gdth_timer
);
3228 GDTH_UNLOCK_HA(ha
, flags
);
3233 int __init
gdth_detect(Scsi_Host_Template
*shtp
)
3235 struct Scsi_Host
*shp
;
3239 int i
,hanum
,cnt
,ctr
;
3244 printk("GDT: This driver contains debugging information !! Trace level = %d\n",
3246 printk(" Destination of debugging information: ");
3249 printk("Serial port COM2\n");
3251 printk("Serial port COM1\n");
3254 printk("Console\n");
3259 TRACE(("gdth_detect()\n"));
3262 printk("GDT: Controller driver disabled from command line !\n");
3266 /* initializations */
3267 gdth_polling
= TRUE
; b
= 0;
3268 gdth_clear_events();
3270 /* scanning for controllers, at first: ISA controller */
3271 for (isa_bios
=0xc8000UL
; isa_bios
<=0xd8000UL
; isa_bios
+=0x8000UL
) {
3272 if (gdth_ctr_count
>= MAXHA
)
3274 if (gdth_search_isa(isa_bios
)) { /* controller found */
3275 shp
= scsi_register(shtp
,sizeof(gdth_ext_str
));
3277 if (!gdth_init_isa(isa_bios
,ha
)) {
3278 scsi_unregister(shp
);
3281 /* controller found and initialized */
3282 printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n",
3283 isa_bios
,ha
->irq
,ha
->drq
);
3285 #if LINUX_VERSION_CODE >= 0x010346
3286 if (request_irq(ha
->irq
,gdth_interrupt
,SA_INTERRUPT
,"gdth",ha
))
3288 if (request_irq(ha
->irq
,gdth_interrupt
,SA_INTERRUPT
,"gdth"))
3291 printk("GDT-ISA: Unable to allocate IRQ\n");
3292 scsi_unregister(shp
);
3295 if (request_dma(ha
->drq
,"gdth")) {
3296 printk("GDT-ISA: Unable to allocate DMA channel\n");
3297 #if LINUX_VERSION_CODE >= 0x010346
3298 free_irq(ha
->irq
,NULL
);
3302 scsi_unregister(shp
);
3305 set_dma_mode(ha
->drq
,DMA_MODE_CASCADE
);
3306 enable_dma(ha
->drq
);
3307 shp
->unchecked_isa_dma
= 1;
3309 shp
->dma_channel
= ha
->drq
;
3310 hanum
= gdth_ctr_count
;
3311 gdth_ctr_tab
[gdth_ctr_count
++] = shp
;
3312 gdth_ctr_vtab
[gdth_ctr_vcount
++] = shp
;
3314 NUMDATA(shp
)->hanum
= (ushort
)hanum
;
3315 NUMDATA(shp
)->busnum
= 0;
3317 ha
->pccb
= CMDDATA(shp
);
3318 ha
->pscratch
= scsi_init_malloc(GDTH_SCRATCH
, GFP_ATOMIC
| GFP_DMA
);
3319 ha
->scratch_busy
= FALSE
;
3320 ha
->req_first
= NULL
;
3321 ha
->tid_cnt
= MAX_HDRIVES
;
3322 if (max_ids
> 0 && max_ids
< ha
->tid_cnt
)
3323 ha
->tid_cnt
= max_ids
;
3324 for (i
=0; i
<GDTH_MAXCMDS
; ++i
)
3325 ha
->cmd_tab
[i
].cmnd
= UNUSED_CMND
;
3326 ha
->scan_mode
= rescan
? 0x10 : 0;
3328 if (ha
->pscratch
== NULL
|| !gdth_search_drives(hanum
)) {
3329 printk("GDT-ISA: Error during device scan\n");
3332 if (ha
->pscratch
!= NULL
)
3333 scsi_init_free((void *)ha
->pscratch
, GDTH_SCRATCH
);
3334 #if LINUX_VERSION_CODE >= 0x010346
3335 free_irq(ha
->irq
,NULL
);
3339 scsi_unregister(shp
);
3342 if (hdr_channel
< 0 || hdr_channel
> ha
->bus_cnt
)
3343 hdr_channel
= ha
->bus_cnt
;
3344 ha
->virt_bus
= hdr_channel
;
3346 #if LINUX_VERSION_CODE >= 0x020000
3347 shp
->max_id
= ha
->tid_cnt
;
3348 shp
->max_lun
= MAXLUN
;
3349 shp
->max_channel
= ha
->bus_cnt
;
3351 /* register addit. SCSI channels as virtual controllers */
3352 for (b
=1; b
<ha
->bus_cnt
+1; ++b
) {
3353 shp
= scsi_register(shtp
,sizeof(gdth_num_str
));
3354 shp
->unchecked_isa_dma
= 1;
3356 shp
->dma_channel
= ha
->drq
;
3357 gdth_ctr_vtab
[gdth_ctr_vcount
++] = shp
;
3358 NUMDATA(shp
)->hanum
= (ushort
)hanum
;
3359 NUMDATA(shp
)->busnum
= b
;
3362 GDTH_INIT_LOCK_HA(ha
);
3363 gdth_enable_int(hanum
);
3367 /* scanning for EISA controllers */
3368 for (eisa_slot
=0x1000; eisa_slot
<=0x8000; eisa_slot
+=0x1000) {
3369 if (gdth_ctr_count
>= MAXHA
)
3371 if (gdth_search_eisa(eisa_slot
)) { /* controller found */
3372 shp
= scsi_register(shtp
,sizeof(gdth_ext_str
));
3374 if (!gdth_init_eisa(eisa_slot
,ha
)) {
3375 scsi_unregister(shp
);
3378 /* controller found and initialized */
3379 printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n",
3380 eisa_slot
>>12,ha
->irq
);
3382 #if LINUX_VERSION_CODE >= 0x010346
3383 if (request_irq(ha
->irq
,gdth_interrupt
,SA_INTERRUPT
,"gdth",ha
))
3385 if (request_irq(ha
->irq
,gdth_interrupt
,SA_INTERRUPT
,"gdth"))
3388 printk("GDT-EISA: Unable to allocate IRQ\n");
3389 scsi_unregister(shp
);
3392 shp
->unchecked_isa_dma
= 0;
3394 shp
->dma_channel
= 0xff;
3395 hanum
= gdth_ctr_count
;
3396 gdth_ctr_tab
[gdth_ctr_count
++] = shp
;
3397 gdth_ctr_vtab
[gdth_ctr_vcount
++] = shp
;
3399 NUMDATA(shp
)->hanum
= (ushort
)hanum
;
3400 NUMDATA(shp
)->busnum
= 0;
3401 TRACE2(("EISA detect Bus 0: hanum %d\n",
3402 NUMDATA(shp
)->hanum
));
3404 ha
->pccb
= CMDDATA(shp
);
3405 ha
->pscratch
= scsi_init_malloc(GDTH_SCRATCH
, GFP_ATOMIC
| GFP_DMA
);
3406 ha
->scratch_busy
= FALSE
;
3407 ha
->req_first
= NULL
;
3408 ha
->tid_cnt
= MAX_HDRIVES
;
3409 if (max_ids
> 0 && max_ids
< ha
->tid_cnt
)
3410 ha
->tid_cnt
= max_ids
;
3411 for (i
=0; i
<GDTH_MAXCMDS
; ++i
)
3412 ha
->cmd_tab
[i
].cmnd
= UNUSED_CMND
;
3413 ha
->scan_mode
= rescan
? 0x10 : 0;
3415 if (ha
->pscratch
== NULL
|| !gdth_search_drives(hanum
)) {
3416 printk("GDT-EISA: Error during device scan\n");
3419 if (ha
->pscratch
!= NULL
)
3420 scsi_init_free((void *)ha
->pscratch
, GDTH_SCRATCH
);
3421 #if LINUX_VERSION_CODE >= 0x010346
3422 free_irq(ha
->irq
,NULL
);
3426 scsi_unregister(shp
);
3429 if (hdr_channel
< 0 || hdr_channel
> ha
->bus_cnt
)
3430 hdr_channel
= ha
->bus_cnt
;
3431 ha
->virt_bus
= hdr_channel
;
3433 #if LINUX_VERSION_CODE >= 0x020000
3434 shp
->max_id
= ha
->tid_cnt
;
3435 shp
->max_lun
= MAXLUN
;
3436 shp
->max_channel
= ha
->bus_cnt
;
3438 /* register addit. SCSI channels as virtual controllers */
3439 for (b
=1; b
<ha
->bus_cnt
+1; ++b
) {
3440 shp
= scsi_register(shtp
,sizeof(gdth_num_str
));
3441 shp
->unchecked_isa_dma
= 0;
3443 shp
->dma_channel
= 0xff;
3444 gdth_ctr_vtab
[gdth_ctr_vcount
++] = shp
;
3445 NUMDATA(shp
)->hanum
= (ushort
)hanum
;
3446 NUMDATA(shp
)->busnum
= b
;
3447 TRACE2(("EISA detect Bus %d: shp %x hanum %d\n",
3448 NUMDATA(shp
)->busnum
,(ulong32
)shp
,
3449 NUMDATA(shp
)->hanum
));
3452 GDTH_INIT_LOCK_HA(ha
);
3453 gdth_enable_int(hanum
);
3457 /* scanning for PCI controllers */
3458 #if LINUX_VERSION_CODE >= 0x2015C
3461 if (pcibios_present())
3464 gdth_pci_str pcistr
[MAXHA
];
3466 cnt
= gdth_search_pci(pcistr
);
3467 gdth_sort_pci(pcistr
,cnt
);
3468 for (ctr
= 0; ctr
< cnt
; ++ctr
) {
3469 if (gdth_ctr_count
>= MAXHA
)
3471 shp
= scsi_register(shtp
,sizeof(gdth_ext_str
));
3473 if (!gdth_init_pci(&pcistr
[ctr
],ha
)) {
3474 scsi_unregister(shp
);
3477 /* controller found and initialized */
3478 printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n",
3479 pcistr
[ctr
].bus
,PCI_SLOT(pcistr
[ctr
].device_fn
),ha
->irq
);
3481 #if LINUX_VERSION_CODE >= 0x010346
3482 if (request_irq(ha
->irq
, gdth_interrupt
,
3483 SA_INTERRUPT
|SA_SHIRQ
, "gdth", ha
))
3485 if (request_irq(ha
->irq
, gdth_interrupt
,
3486 SA_INTERRUPT
|SA_SHIRQ
, "gdth"))
3489 printk("GDT-PCI: Unable to allocate IRQ\n");
3490 scsi_unregister(shp
);
3493 shp
->unchecked_isa_dma
= 0;
3495 shp
->dma_channel
= 0xff;
3496 hanum
= gdth_ctr_count
;
3497 gdth_ctr_tab
[gdth_ctr_count
++] = shp
;
3498 gdth_ctr_vtab
[gdth_ctr_vcount
++] = shp
;
3500 NUMDATA(shp
)->hanum
= (ushort
)hanum
;
3501 NUMDATA(shp
)->busnum
= 0;
3503 ha
->pccb
= CMDDATA(shp
);
3504 ha
->pscratch
= scsi_init_malloc(GDTH_SCRATCH
, GFP_ATOMIC
| GFP_DMA
);
3505 ha
->scratch_busy
= FALSE
;
3506 ha
->req_first
= NULL
;
3507 ha
->tid_cnt
= pcistr
[ctr
].device_id
>= 0x200 ? MAXID
: MAX_HDRIVES
;
3508 if (max_ids
> 0 && max_ids
< ha
->tid_cnt
)
3509 ha
->tid_cnt
= max_ids
;
3510 for (i
=0; i
<GDTH_MAXCMDS
; ++i
)
3511 ha
->cmd_tab
[i
].cmnd
= UNUSED_CMND
;
3512 ha
->scan_mode
= rescan
? 0x10 : 0;
3514 if (ha
->pscratch
== NULL
|| !gdth_search_drives(hanum
)) {
3515 printk("GDT-PCI: Error during device scan\n");
3518 if (ha
->pscratch
!= NULL
)
3519 scsi_init_free((void *)ha
->pscratch
, GDTH_SCRATCH
);
3520 #if LINUX_VERSION_CODE >= 0x010346
3521 free_irq(ha
->irq
,NULL
);
3525 scsi_unregister(shp
);
3528 if (hdr_channel
< 0 || hdr_channel
> ha
->bus_cnt
)
3529 hdr_channel
= ha
->bus_cnt
;
3530 ha
->virt_bus
= hdr_channel
;
3532 #if LINUX_VERSION_CODE >= 0x020000
3533 shp
->max_id
= ha
->tid_cnt
;
3534 shp
->max_lun
= MAXLUN
;
3535 shp
->max_channel
= ha
->bus_cnt
;
3537 /* register addit. SCSI channels as virtual controllers */
3538 for (b
=1; b
<ha
->bus_cnt
+1; ++b
) {
3539 shp
= scsi_register(shtp
,sizeof(gdth_num_str
));
3540 shp
->unchecked_isa_dma
= 0;
3542 shp
->dma_channel
= 0xff;
3543 gdth_ctr_vtab
[gdth_ctr_vcount
++] = shp
;
3544 NUMDATA(shp
)->hanum
= (ushort
)hanum
;
3545 NUMDATA(shp
)->busnum
= b
;
3548 GDTH_INIT_LOCK_HA(ha
);
3549 gdth_enable_int(hanum
);
3553 TRACE2(("gdth_detect() %d controller detected\n",gdth_ctr_count
));
3554 if (gdth_ctr_count
> 0) {
3555 #ifdef GDTH_STATISTICS
3556 TRACE2(("gdth_detect(): Initializing timer !\n"));
3557 init_timer(&gdth_timer
);
3558 gdth_timer
.expires
= jiffies
+ HZ
;
3559 gdth_timer
.data
= 0L;
3560 gdth_timer
.function
= gdth_timeout
;
3561 add_timer(&gdth_timer
);
3563 #if LINUX_VERSION_CODE >= 0x020100
3564 register_reboot_notifier(&gdth_notifier
);
3567 gdth_polling
= FALSE
;
3568 return gdth_ctr_vcount
;
3572 int gdth_release(struct Scsi_Host
*shp
)
3577 TRACE2(("gdth_release()\n"));
3578 if (NUMDATA(shp
)->busnum
== 0) {
3579 hanum
= NUMDATA(shp
)->hanum
;
3580 ha
= HADATA(gdth_ctr_tab
[hanum
]);
3581 #if LINUX_VERSION_CODE >= 0x010300
3586 #if LINUX_VERSION_CODE >= 0x010346
3587 free_irq(shp
->irq
,NULL
);
3592 if (shp
->dma_channel
!= 0xff) {
3593 free_dma(shp
->dma_channel
);
3595 scsi_init_free((void *)ha
->pscratch
, GDTH_SCRATCH
);
3596 gdth_ctr_released
++;
3597 TRACE2(("gdth_release(): HA %d of %d\n",
3598 gdth_ctr_released
, gdth_ctr_count
));
3600 if (gdth_ctr_released
== gdth_ctr_count
) {
3601 #ifdef GDTH_STATISTICS
3602 del_timer(&gdth_timer
);
3604 #if LINUX_VERSION_CODE >= 0x020100
3605 unregister_reboot_notifier(&gdth_notifier
);
3610 scsi_unregister(shp
);
3615 static const char *gdth_ctr_name(int hanum
)
3619 TRACE2(("gdth_ctr_name()\n"));
3621 ha
= HADATA(gdth_ctr_tab
[hanum
]);
3623 if (ha
->type
== GDT_EISA
) {
3624 switch (ha
->stype
) {
3626 return("GDT3000/3020");
3628 return("GDT3000A/3020A/3050A");
3630 return("GDT3000B/3010A");
3632 } else if (ha
->type
== GDT_ISA
) {
3633 return("GDT2000/2020");
3634 } else if (ha
->type
== GDT_PCI
) {
3635 switch (ha
->stype
) {
3636 case PCI_DEVICE_ID_VORTEX_GDT60x0
:
3637 return("GDT6000/6020/6050");
3638 case PCI_DEVICE_ID_VORTEX_GDT6000B
:
3639 return("GDT6000B/6010");
3642 /* new controllers (GDT_PCINEW, GDT_PCIMPR, ..) use board_info IOCTL! */
3647 const char *gdth_info(struct Scsi_Host
*shp
)
3652 TRACE2(("gdth_info()\n"));
3653 hanum
= NUMDATA(shp
)->hanum
;
3654 ha
= HADATA(gdth_ctr_tab
[hanum
]);
3656 return ((const char *)ha
->binfo
.type_string
);
3659 /* old error handling */
3660 int gdth_abort(Scsi_Cmnd
*scp
)
3662 TRACE2(("gdth_abort() reason %d\n",scp
->abort_reason
));
3663 return SCSI_ABORT_SNOOZE
;
3666 #if LINUX_VERSION_CODE >= 0x010346
3667 int gdth_reset(Scsi_Cmnd
*scp
, unsigned int reset_flags
)
3669 int gdth_reset(Scsi_Cmnd
*scp
)
3672 TRACE2(("gdth_reset()\n"));
3673 return SCSI_RESET_PUNT
;
3676 #if LINUX_VERSION_CODE >= 0x02015F
3677 /* new error handling */
3678 int gdth_eh_abort(Scsi_Cmnd
*scp
)
3680 TRACE2(("gdth_eh_abort()\n"));
3684 int gdth_eh_device_reset(Scsi_Cmnd
*scp
)
3686 TRACE2(("gdth_eh_device_reset()\n"));
3690 int gdth_eh_bus_reset(Scsi_Cmnd
*scp
)
3697 TRACE2(("gdth_eh_bus_reset()\n"));
3698 hanum
= NUMDATA(scp
->host
)->hanum
;
3699 ha
= HADATA(gdth_ctr_tab
[hanum
]);
3700 if (scp
->channel
== ha
->virt_bus
)
3703 GDTH_LOCK_HA(ha
, flags
);
3704 for (i
= 0; i
< MAXID
; ++i
)
3705 ha
->raw
[BUS_L2P(ha
,scp
->channel
)].io_cnt
[i
] = 0;
3706 for (i
= 0; i
< GDTH_MAXCMDS
; ++i
) {
3707 cmnd
= ha
->cmd_tab
[i
].cmnd
;
3708 if (!SPECIAL_SCP(cmnd
) && cmnd
->channel
== scp
->channel
)
3709 ha
->cmd_tab
[i
].cmnd
= UNUSED_CMND
;
3711 gdth_polling
= TRUE
;
3712 while (gdth_test_busy(hanum
))
3714 gdth_internal_cmd(hanum
, SCSIRAWSERVICE
, GDT_RESET_BUS
,
3715 BUS_L2P(ha
,scp
->channel
), 0, 0);
3716 gdth_polling
= FALSE
;
3717 GDTH_UNLOCK_HA(ha
, flags
);
3721 int gdth_eh_host_reset(Scsi_Cmnd
*scp
)
3723 TRACE2(("gdth_eh_host_reset()\n"));
3728 #if LINUX_VERSION_CODE >= 0x010300
3729 int gdth_bios_param(Disk
*disk
,kdev_t dev
,int *ip
)
3731 int gdth_bios_param(Disk
*disk
,int dev
,int *ip
)
3738 hanum
= NUMDATA(disk
->device
->host
)->hanum
;
3739 t
= disk
->device
->id
;
3740 TRACE2(("gdth_bios_param() ha %d bus %d target %d\n",
3741 hanum
, disk
->device
->channel
, t
));
3742 ha
= HADATA(gdth_ctr_tab
[hanum
]);
3744 if (disk
->device
->channel
!= ha
->virt_bus
|| ha
->hdr
[t
].heads
== 0) {
3745 /* raw device or host drive without mapping information */
3746 TRACE2(("Evaluate mapping\n"));
3747 gdth_eval_mapping(disk
->capacity
,&ip
[2],&ip
[0],&ip
[1]);
3749 ip
[0] = ha
->hdr
[t
].heads
;
3750 ip
[1] = ha
->hdr
[t
].secs
;
3751 ip
[2] = disk
->capacity
/ ip
[0] / ip
[1];
3754 TRACE2(("gdth_bios_param(): %d heads, %d secs, %d cyls\n",
3755 ip
[0],ip
[1],ip
[2]));
3760 static void internal_done(Scsi_Cmnd
*scp
)
3762 scp
->SCp
.sent_command
++;
3765 int gdth_command(Scsi_Cmnd
*scp
)
3767 TRACE2(("gdth_command()\n"));
3769 scp
->SCp
.sent_command
= 0;
3770 gdth_queuecommand(scp
,internal_done
);
3772 while (!scp
->SCp
.sent_command
)
3778 int gdth_queuecommand(Scsi_Cmnd
*scp
,void (*done
)(Scsi_Cmnd
*))
3783 TRACE(("gdth_queuecommand() cmd 0x%x id %d lun %d\n",
3784 scp
->cmnd
[0],scp
->target
,scp
->lun
));
3786 scp
->scsi_done
= (void *)done
;
3787 scp
->SCp
.have_data_in
= 1;
3788 scp
->SCp
.phase
= -1;
3789 scp
->SCp
.Status
= -1;
3790 hanum
= NUMDATA(scp
->host
)->hanum
;
3791 #ifdef GDTH_STATISTICS
3795 priority
= DEFAULT_PRI
;
3796 #if LINUX_VERSION_CODE >= 0x010300
3797 if (scp
->done
== gdth_scsi_done
)
3798 priority
= scp
->SCp
.this_residual
;
3800 gdth_update_timeout(hanum
, scp
, scp
->timeout_per_command
* 6);
3801 gdth_putq( hanum
, scp
, priority
);
3806 #if LINUX_VERSION_CODE >= 0x010300
3808 static void gdth_flush(int hanum
)
3814 gdth_cmd_str gdtcmd
;
3816 TRACE2(("gdth_flush() hanum %d\n",hanum
));
3817 ha
= HADATA(gdth_ctr_tab
[hanum
]);
3818 memset(&sdev
,0,sizeof(Scsi_Device
));
3819 memset(&scp
, 0,sizeof(Scsi_Cmnd
));
3820 sdev
.host
= gdth_ctr_tab
[hanum
];
3821 sdev
.id
= sdev
.host
->this_id
;
3823 scp
.host
= gdth_ctr_tab
[hanum
];
3824 scp
.target
= sdev
.host
->this_id
;
3828 for (i
= 0; i
< MAX_HDRIVES
; ++i
) {
3829 if (ha
->hdr
[i
].present
) {
3830 gdtcmd
.BoardNode
= LOCALBOARD
;
3831 gdtcmd
.Service
= CACHESERVICE
;
3832 gdtcmd
.OpCode
= GDT_FLUSH
;
3833 gdtcmd
.u
.cache
.DeviceNo
= i
;
3834 gdtcmd
.u
.cache
.BlockNo
= 1;
3835 gdtcmd
.u
.cache
.sg_canz
= 0;
3836 TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum
, i
));
3837 gdth_do_cmd(&scp
, &gdtcmd
, 30);
3842 /* shutdown routine */
3843 #if LINUX_VERSION_CODE >= 0x020100
3844 static int gdth_halt(struct notifier_block
*nb
, ulong event
, void *buf
)
3846 void gdth_halt(void)
3853 gdth_cmd_str gdtcmd
;
3856 #if LINUX_VERSION_CODE >= 0x020100
3857 TRACE2(("gdth_halt() event %d\n",event
));
3858 if (event
!= SYS_RESTART
&& event
!= SYS_HALT
&& event
!= SYS_POWER_OFF
)
3861 TRACE2(("gdth_halt()\n"));
3863 TRACE2(("already called\n"));
3868 printk("GDT: Flushing all host drives .. ");
3869 for (hanum
= 0; hanum
< gdth_ctr_count
; ++hanum
) {
3873 /* controller reset */
3874 memset(&sdev
,0,sizeof(Scsi_Device
));
3875 memset(&scp
, 0,sizeof(Scsi_Cmnd
));
3876 sdev
.host
= gdth_ctr_tab
[hanum
];
3877 sdev
.id
= sdev
.host
->this_id
;
3879 scp
.host
= gdth_ctr_tab
[hanum
];
3880 scp
.target
= sdev
.host
->this_id
;
3884 gdtcmd
.BoardNode
= LOCALBOARD
;
3885 gdtcmd
.Service
= CACHESERVICE
;
3886 gdtcmd
.OpCode
= GDT_RESET
;
3887 TRACE2(("gdth_halt(): reset controller %d\n", hanum
));
3888 gdth_do_cmd(&scp
, &gdtcmd
, 10);
3893 #ifdef GDTH_STATISTICS
3894 del_timer(&gdth_timer
);
3896 #if LINUX_VERSION_CODE >= 0x020100
3897 unregister_reboot_notifier(&gdth_notifier
);
3904 /* called from init/main.c */
3905 void __init
gdth_setup(char *str
,int *ints
)
3908 char *cur_str
, *argv
;
3910 TRACE2(("gdth_setup() str %s ints[0] %d\n",
3911 str
? str
:"NULL", ints
? ints
[0]:0));
3913 /* read irq[] from ints[] */
3919 for (i
= 0; i
< argc
; ++i
)
3924 /* analyse string */
3926 while (argv
&& (cur_str
= strchr(argv
, ':'))) {
3927 int val
= 0, c
= *++cur_str
;
3929 if (c
== 'n' || c
== 'N')
3931 else if (c
== 'y' || c
== 'Y')
3934 val
= (int)simple_strtoul(cur_str
, NULL
, 0);
3936 if (!strncmp(argv
, "disable:", 8))
3938 else if (!strncmp(argv
, "reserve_mode:", 13))
3940 else if (!strncmp(argv
, "reverse_scan:", 13))
3942 else if (!strncmp(argv
, "hdr_channel:", 12))
3944 else if (!strncmp(argv
, "max_ids:", 8))
3946 else if (!strncmp(argv
, "rescan:", 7))
3948 else if (!strncmp(argv
, "reserve_list:", 13)) {
3949 reserve_list
[0] = val
;
3950 for (i
= 1; i
< MAX_RES_ARGS
; i
++) {
3951 cur_str
= strchr(cur_str
, ',');
3954 if (!isdigit((int)*++cur_str
)) {
3959 (int)simple_strtoul(cur_str
, NULL
, 0);
3967 if ((argv
= strchr(argv
, ',')))
3974 Scsi_Host_Template driver_template
= GDTH
;
3975 #include "scsi_module.c"