Annotation of Gnu-Mach/linux/src/drivers/scsi/gdth.c, revision 1.1.1.1

1.1       root        1: /************************************************************************
                      2:  * GDT ISA/EISA/PCI Disk Array Controller driver for Linux              *
                      3:  *                                                                      *
                      4:  * gdth.c                                                               *
                      5:  * Copyright (C) 1995-98 ICP vortex Computersysteme GmbH, Achim Leubner *
                      6:  *                                                                      *
                      7:  * <[email protected]>                                                    *
                      8:  *                                                                      *
                      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.                               *
                     13:  *                                                                      *
                     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.                         *
                     18:  *                                                                      *
                     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.            *
                     22:  *                                                                      *
                     23:  * Tested with Linux 1.2.13, ..., 2.1.103                               *
                     24:  *                                                                      *
                     25:  * $Log: gdth.c,v $
                     26:  * Revision 1.1  1999/04/26 05:54:35  tb
                     27:  * 1998-11-30  OKUJI Yoshinori  <[email protected]>
                     28:  *
                     29:  *     Clean up linux emulation code to make it architecture-independent
                     30:  *     as much as possible.
                     31:  *
                     32:  *     * linux: Renamed from linuxdev.
                     33:  *     * Makefile.in (objfiles): Add linux.o instead of linuxdev.o.
                     34:  *     (MAKE): New variable. Used for the linux.o target.
                     35:  *     * configure.in: Add AC_CHECK_TOOL(MAKE, make).
                     36:  *     * i386/i386/spl.h: Include <i386/ipl.h>, for compatibility with
                     37:  *     OSF Mach 3.0. Suggested by Elgin Lee <[email protected]>.
                     38:  *     * linux/src: Renamed from linux/linux.
                     39:  *     * linux/dev: Renamed from linux/mach.
                     40:  *     * linux/Drivers.in (AC_INIT): Use dev/include/linux/autoconf.h,
                     41:  *     instead of mach/include/linux/autoconf.h.
                     42:  *     * Makefile.in (all): Target ../linux.o instead of ../linuxdev.o.
                     43:  *     * linux/dev/drivers/block/genhd.c: Include <machine/spl.h> instead
                     44:  *     of <i386/ipl.h>.
                     45:  *     * linux/dev/drivers/net/auto_irq.c: Remove unneeded header files,
                     46:  *     <i386/ipl.h> and <i386/pic.h>.
                     47:  *     * linux/dev/init/main.c: Many i386-dependent codes moved to ...
                     48:  *     * linux/dev/arch/i386/irq.c: ... here.
                     49:  *     * linux/dev/arch/i386/setup.c: New file.
                     50:  *     * linux/dev/arch/i386/linux_emul.h: Likewise.
                     51:  *     * linux/dev/arch/i386/glue/timer.c: Merged into sched.c.
                     52:  *     * linux/dev/arch/i386/glue/sched.c: Include <machine/spl.h> instead
                     53:  *     of <i386/ipl.h>, and moved to ...
                     54:  *     * linux/dev/kernel/sched.c: ... here.
                     55:  *     * linux/dev/arch/i386/glue/block.c: Include <machine/spl.h> and
                     56:  *     <linux_emul.h>, instead of i386-dependent header files, and
                     57:  *     moved to ...
                     58:  *     * linux/dev/glue/blocl.c: ... here.
                     59:  *     * linux/dev/arch/i386/glue/net.c: Include <machine/spl.h> and
                     60:  *     <linux_emul.h>, instead of i386-dependent header files, and
                     61:  *     moved to ...
                     62:  *     * linux/dev/glue/net.c: ... here.
                     63:  *     * linux/dev/arch/i386/glue/misc.c: Remove `x86' and moved to ...
                     64:  *     * linux/dev/glue/misc.c: ... here.
                     65:  *     * linux/dev/arch/i386/glue/kmem.c: Moved to ...
                     66:  *     * linux/dev/glue/kmem.c: ... here.
                     67:  *
                     68:  * Revision 1.16  1998/09/28 16:08:46  achim
                     69:  * GDT_PCIMPR: DPMEM remapping, if required
                     70:  * mdelay() added
                     71:  *
                     72:  * Revision 1.15  1998/06/03 14:54:06  achim
                     73:  * gdth_delay(), gdth_flush() implemented
                     74:  * Bugfix: gdth_release() changed
                     75:  *
                     76:  * Revision 1.14  1998/05/22 10:01:17  achim
                     77:  * mj: pcibios_strerror() removed
                     78:  * Improved SMP support (if version >= 2.1.95)
                     79:  * gdth_halt(): halt_called flag added (if version < 2.1)
                     80:  *
                     81:  * Revision 1.13  1998/04/16 09:14:57  achim
                     82:  * Reserve drives (for raw service) implemented
                     83:  * New error handling code enabled
                     84:  * Get controller name from board_info() IOCTL
                     85:  * Final round of PCI device driver patches by Martin Mares
                     86:  *
                     87:  * Revision 1.12  1998/03/03 09:32:37  achim
                     88:  * Fibre channel controller support added
                     89:  *
                     90:  * Revision 1.11  1998/01/27 16:19:14  achim
                     91:  * SA_SHIRQ added
                     92:  * add_timer()/del_timer() instead of GDTH_TIMER
                     93:  * scsi_add_timer()/scsi_del_timer() instead of SCSI_TIMER
                     94:  * New error handling included
                     95:  *
                     96:  * Revision 1.10  1997/10/31 12:29:57  achim
                     97:  * Read heads/sectors from host drive
                     98:  *
                     99:  * Revision 1.9  1997/09/04 10:07:25  achim
                    100:  * IO-mapping with virt_to_bus(), readb(), writeb(), ...
                    101:  * register_reboot_notifier() to get a notify on shutdown used
                    102:  *
                    103:  * Revision 1.8  1997/04/02 12:14:30  achim
                    104:  * Version 1.00 (see gdth.h), tested with kernel 2.0.29
                    105:  *
                    106:  * Revision 1.7  1997/03/12 13:33:37  achim
                    107:  * gdth_reset() changed, new async. events
                    108:  *
                    109:  * Revision 1.6  1997/03/04 14:01:11  achim
                    110:  * Shutdown routine gdth_halt() implemented
                    111:  *
                    112:  * Revision 1.5  1997/02/21 09:08:36  achim
                    113:  * New controller included (RP, RP1, RP2 series)
                    114:  * IOCTL interface implemented
                    115:  *
                    116:  * Revision 1.4  1996/07/05 12:48:55  achim
                    117:  * Function gdth_bios_param() implemented
                    118:  * New constant GDTH_MAXC_P_L inserted
                    119:  * GDT_WRITE_THR, GDT_EXT_INFO implemented
                    120:  * Function gdth_reset() changed
                    121:  *
                    122:  * Revision 1.3  1996/05/10 09:04:41  achim
                    123:  * Small changes for Linux 1.2.13
                    124:  *
                    125:  * Revision 1.2  1996/05/09 12:45:27  achim
                    126:  * Loadable module support implemented
                    127:  * /proc support corrections made
                    128:  *
                    129:  * Revision 1.1  1996/04/11 07:35:57  achim
                    130:  * Initial revision
                    131:  *
                    132:  *
                    133:  * $Id: gdth.c,v 1.1 1999/04/26 05:54:35 tb Exp $ 
                    134:  ************************************************************************/
                    135: 
                    136: #ifdef MODULE
                    137: #include <linux/module.h>
                    138: #endif
                    139: 
                    140: #include <linux/version.h>
                    141: #include <linux/kernel.h>
                    142: #include <linux/head.h>
                    143: #include <linux/types.h>
                    144: #include <linux/pci.h>
                    145: #include <linux/string.h>
                    146: #include <linux/ioport.h>
                    147: #include <linux/delay.h>
                    148: #include <linux/sched.h>
                    149: #include <linux/in.h>
                    150: #include <linux/proc_fs.h>
                    151: #include <linux/time.h>
                    152: #include <linux/timer.h>
                    153: #if LINUX_VERSION_CODE >= 0x020100
                    154: #include <linux/reboot.h>
                    155: #else
                    156: #include <linux/bios32.h>
                    157: #endif
                    158: 
                    159: #include <asm/dma.h>
                    160: #include <asm/system.h>
                    161: #include <asm/io.h>
                    162: #if LINUX_VERSION_CODE >= 0x02015F
                    163: #include <asm/spinlock.h>
                    164: #endif
                    165: 
                    166: #if LINUX_VERSION_CODE >= 0x010300
                    167: #include <linux/blk.h>
                    168: #else
                    169: #include "../block/blk.h"
                    170: #endif
                    171: #include "scsi.h"
                    172: #include "hosts.h"
                    173: #include "sd.h"
                    174: 
                    175: #include "gdth.h"
                    176: 
                    177: /****************************************************************************/
                    178: 
                    179: /* LILO params: gdth=<IRQ>
                    180:  *
                    181:  * Where: <IRQ> is any of the valid IRQs for EISA controllers (10,11,12,14)
                    182:  * Sets the IRQ of the GDT3000/3020 EISA controller to this value,
                    183:  * if the IRQ can not automat. detect (controller BIOS disabled)
                    184:  * See gdth_init_eisa() 
                    185:  *
                    186:  * You can use the command line gdth=0 to disable the driver 
                    187:  */
                    188: static unchar irqs[MAXHA] = {0xff};
                    189: static unchar disable_gdth_scan = FALSE;
                    190: 
                    191: /* Reserve drives for raw service: Fill the following structure with the
                    192:  * appropriate values: Controller number, Channel, Target ID 
                    193:  */
                    194: static gdth_reserve_str reserve_list[] = {
                    195:     /* { 0, 1, 4 },            Example: Controller 0, Channel B, ID 4 */
                    196:     { 0xff, 0xff, 0xff }       /* end of list */
                    197: };
                    198: 
                    199: /****************************************************************************/
                    200: 
                    201: #if LINUX_VERSION_CODE >= 0x02015F
                    202: static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs);
                    203: static void do_gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs);
                    204: #elif LINUX_VERSION_CODE >= 0x010346
                    205: static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs);
                    206: #else
                    207: static void gdth_interrupt(int irq,struct pt_regs *regs);
                    208: #endif
                    209: static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp);
                    210: static int gdth_async_event(int hanum,int service);
                    211: 
                    212: static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority);
                    213: static void gdth_next(int hanum);
                    214: static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b);
                    215: static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp,unchar b);
                    216: static gdth_evt_str *gdth_store_event(ushort source, ushort idx,
                    217:                                       gdth_evt_data *evt);
                    218: static int gdth_read_event(int handle, gdth_evt_str *estr);
                    219: static void gdth_readapp_event(unchar application, gdth_evt_str *estr);
                    220: static void gdth_clear_events(void);
                    221: 
                    222: static void gdth_copy_internal_data(Scsi_Cmnd *scp,char *buffer,ushort count);
                    223: static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp,
                    224:                                    unchar b,ulong *flags);
                    225: static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive);
                    226: 
                    227: static int gdth_search_eisa(ushort eisa_adr);
                    228: static int gdth_search_isa(ulong bios_adr);
                    229: static int gdth_search_pci(ushort device_id,ushort index,gdth_pci_str *pcistr);
                    230: static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha);
                    231: static int gdth_init_isa(ulong bios_adr,gdth_ha_str *ha);
                    232: static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha);
                    233: 
                    234: static void gdth_enable_int(int hanum);
                    235: static int gdth_get_status(unchar *pIStatus,int irq);
                    236: static int gdth_test_busy(int hanum);
                    237: static int gdth_get_cmd_index(int hanum);
                    238: static void gdth_release_event(int hanum);
                    239: static int gdth_wait(int hanum,int index,ulong time);
                    240: static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong p1,
                    241:                              ulong p2,ulong p3);
                    242: static int gdth_search_drives(int hanum);
                    243: 
                    244: static void *gdth_mmap(ulong paddr, ulong size);
                    245: static void gdth_munmap(void *addr);
                    246: 
                    247: static const char *gdth_ctr_name(int hanum);
                    248: 
                    249: static void gdth_flush(int hanum);
                    250: #if LINUX_VERSION_CODE >= 0x020100
                    251: static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
                    252: #else
                    253: static int halt_called = FALSE;
                    254: void gdth_halt(void);
                    255: #endif
                    256: 
                    257: #ifdef DEBUG_GDTH
                    258: static unchar   DebugState = DEBUG_GDTH;
                    259: extern int sys_syslog(int,char*,int);
                    260: #define LOGEN           sys_syslog(7,NULL,0)
                    261: 
                    262: #ifdef __SERIAL__
                    263: #define MAX_SERBUF 160
                    264: static void ser_init(void);
                    265: static void ser_puts(char *str);
                    266: static void ser_putc(char c);
                    267: static int  ser_printk(const char *fmt, ...);
                    268: static char strbuf[MAX_SERBUF+1];
                    269: #ifdef __COM2__
                    270: #define COM_BASE 0x2f8
                    271: #else
                    272: #define COM_BASE 0x3f8
                    273: #endif
                    274: static void ser_init()
                    275: {
                    276:     unsigned port=COM_BASE;
                    277: 
                    278:     outb(0x80,port+3);
                    279:     outb(0,port+1);
                    280:     /* 19200 Baud, if 9600: outb(12,port) */
                    281:     outb(6, port);
                    282:     outb(3,port+3);
                    283:     outb(0,port+1);
                    284:     /*
                    285:     ser_putc('I');
                    286:     ser_putc(' ');
                    287:     */
                    288: }
                    289: 
                    290: static void ser_puts(char *str)
                    291: {
                    292:     char *ptr;
                    293: 
                    294:     ser_init();
                    295:     for (ptr=str;*ptr;++ptr)
                    296:         ser_putc(*ptr);
                    297: }
                    298: 
                    299: static void ser_putc(char c)
                    300: {
                    301:     unsigned port=COM_BASE;
                    302: 
                    303:     while ((inb(port+5) & 0x20)==0);
                    304:     outb(c,port);
                    305:     if (c==0x0a)
                    306:     {
                    307:         while ((inb(port+5) & 0x20)==0);
                    308:         outb(0x0d,port);
                    309:     }
                    310: }
                    311: 
                    312: static int ser_printk(const char *fmt, ...)
                    313: {
                    314:     va_list args;
                    315:     int i;
                    316: 
                    317:     va_start(args,fmt);
                    318:     i = vsprintf(strbuf,fmt,args);
                    319:     ser_puts(strbuf);
                    320:     va_end(args);
                    321:     return i;
                    322: }
                    323: 
                    324: #define TRACE(a)    {if (DebugState==1) {ser_printk a;}}
                    325: #define TRACE2(a)   {if (DebugState==1 || DebugState==2) {ser_printk a;}}
                    326: #define TRACE3(a)   {if (DebugState!=0) {ser_printk a;}}
                    327: 
                    328: #else /* !__SERIAL__ */
                    329: #define TRACE(a)    {if (DebugState==1) {LOGEN;printk a;}}
                    330: #define TRACE2(a)   {if (DebugState==1 || DebugState==2) {LOGEN;printk a;}}
                    331: #define TRACE3(a)   {if (DebugState!=0) {LOGEN;printk a;}}
                    332: #endif
                    333: 
                    334: #else /* !DEBUG */
                    335: #define TRACE(a)
                    336: #define TRACE2(a)
                    337: #define TRACE3(a)
                    338: #endif
                    339: 
                    340: #ifdef GDTH_STATISTICS
                    341: static ulong max_rq=0, max_index=0, max_sg=0;
                    342: static ulong act_ints=0, act_ios=0, act_stats=0, act_rq=0;
                    343: static struct timer_list gdth_timer;
                    344: #endif
                    345: 
                    346: #define PTR2USHORT(a)   (ushort)(ulong)(a)
                    347: #define GDTOFFSOF(a,b)  (size_t)&(((a*)0)->b)   
                    348: #define INDEX_OK(i,t)   ((i)<sizeof(t)/sizeof((t)[0]))
                    349: 
                    350: #define NUMDATA(a)      ( (gdth_num_str  *)((a)->hostdata))
                    351: #define HADATA(a)       (&((gdth_ext_str *)((a)->hostdata))->haext)
                    352: #define CMDDATA(a)      (&((gdth_ext_str *)((a)->hostdata))->cmdext)
                    353: #define DMADATA(a)      (&((gdth_ext_str *)((a)->hostdata))->dmaext)
                    354: 
                    355: 
                    356: #if LINUX_VERSION_CODE < 0x010300
                    357: static void *gdth_mmap(ulong paddr, ulong size) 
                    358: {
                    359:     if (paddr >= high_memory)
                    360:        return NULL; 
                    361:     else
                    362:        return (void *)paddr;
                    363: }
                    364: static void gdth_munmap(void *addr) 
                    365: {
                    366: }
                    367: inline ulong virt_to_phys(volatile void *addr)
                    368: {
                    369:     return (ulong)addr;
                    370: }
                    371: inline void *phys_to_virt(ulong addr)
                    372: {
                    373:     return (void *)addr;
                    374: }
                    375: #define virt_to_bus            virt_to_phys
                    376: #define bus_to_virt            phys_to_virt
                    377: #define readb(addr)            (*(volatile unchar *)(addr))
                    378: #define readw(addr)            (*(volatile ushort *)(addr))
                    379: #define readl(addr)            (*(volatile ulong *)(addr))
                    380: #define writeb(b,addr)         (*(volatile unchar *)(addr) = (b))
                    381: #define writew(b,addr)         (*(volatile ushort *)(addr) = (b))
                    382: #define writel(b,addr)         (*(volatile ulong *)(addr) = (b))
                    383: #define memset_io(a,b,c)       memset((void *)(a),(b),(c))
                    384: #define memcpy_fromio(a,b,c)   memcpy((a),(void *)(b),(c))
                    385: #define memcpy_toio(a,b,c)     memcpy((void *)(a),(b),(c))
                    386: 
                    387: #elif LINUX_VERSION_CODE < 0x020100
                    388: static int remapped = FALSE;
                    389: static void *gdth_mmap(ulong paddr, ulong size) 
                    390: {
                    391:     if ( paddr >= high_memory) {
                    392:        remapped = TRUE;
                    393:        return vremap(paddr, size);
                    394:     } else {
                    395:        return (void *)paddr; 
                    396:     }
                    397: }
                    398: static void gdth_munmap(void *addr) 
                    399: {
                    400:     if (remapped)
                    401:        vfree(addr);
                    402:     remapped = FALSE;
                    403: }
                    404: #else
                    405: static void *gdth_mmap(ulong paddr, ulong size) 
                    406: { 
                    407:     return ioremap(paddr, size); 
                    408: }
                    409: static void gdth_munmap(void *addr) 
                    410: {
                    411:     return iounmap(addr);
                    412: }
                    413: #endif
                    414: 
                    415: 
                    416: static unchar   gdth_drq_tab[4] = {5,6,7,7};            /* DRQ table */
                    417: static unchar   gdth_irq_tab[6] = {0,10,11,12,14,0};    /* IRQ table */
                    418: static unchar   gdth_polling;                           /* polling if TRUE */
                    419: static unchar   gdth_from_wait  = FALSE;                /* gdth_wait() */
                    420: static int      wait_index,wait_hanum;                  /* gdth_wait() */
                    421: static int      gdth_ctr_count  = 0;                    /* controller count */
                    422: static int      gdth_ctr_vcount = 0;                    /* virt. ctr. count */
                    423: static int     gdth_ctr_released = 0;                  /* gdth_release() */
                    424: static struct Scsi_Host *gdth_ctr_tab[MAXHA];           /* controller table */
                    425: static struct Scsi_Host *gdth_ctr_vtab[MAXHA*MAXBUS];   /* virt. ctr. table */
                    426: static unchar   gdth_write_through = FALSE;             /* write through */
                    427: static char *gdth_ioctl_tab[4][MAXHA];                  /* ioctl buffer */
                    428: static gdth_evt_str ebuffer[MAX_EVENTS];                /* event buffer */
                    429: static int elastidx;
                    430: static int eoldidx;
                    431: 
                    432: static struct {
                    433:     Scsi_Cmnd   *cmnd;                          /* pending request */
                    434:     ushort      service;                        /* service */
                    435: } gdth_cmd_tab[GDTH_MAXCMDS][MAXHA];            /* table of pend. requests */
                    436: 
                    437: #define DIN     1                               /* IN data direction */
                    438: #define DOU     2                               /* OUT data direction */
                    439: #define DNO     DIN                             /* no data transfer */
                    440: #define DUN     DIN                             /* unknown data direction */
                    441: static unchar gdth_direction_tab[0x100] = {
                    442:     DNO,DNO,DIN,DIN,DOU,DIN,DIN,DOU,DIN,DUN,DOU,DOU,DUN,DUN,DUN,DIN,
                    443:     DNO,DIN,DIN,DOU,DIN,DOU,DNO,DNO,DOU,DNO,DIN,DNO,DIN,DOU,DNO,DUN,
                    444:     DIN,DUN,DIN,DUN,DOU,DIN,DUN,DUN,DIN,DIN,DIN,DUN,DUN,DIN,DIN,DIN,
                    445:     DIN,DIN,DIN,DNO,DIN,DNO,DNO,DIN,DIN,DIN,DIN,DIN,DIN,DIN,DIN,DIN,
                    446:     DIN,DIN,DIN,DIN,DIN,DNO,DUN,DNO,DNO,DNO,DUN,DNO,DIN,DIN,DUN,DUN,
                    447:     DUN,DUN,DUN,DUN,DUN,DIN,DUN,DUN,DUN,DUN,DIN,DUN,DUN,DUN,DUN,DUN,
                    448:     DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
                    449:     DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
                    450:     DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
                    451:     DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
                    452:     DUN,DUN,DUN,DUN,DUN,DNO,DNO,DUN,DIN,DNO,DIN,DUN,DNO,DUN,DIN,DIN,
                    453:     DIN,DIN,DIN,DNO,DUN,DIN,DIN,DIN,DIN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
                    454:     DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
                    455:     DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
                    456:     DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,
                    457:     DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN
                    458: };
                    459: 
                    460: /* __initfunc, __initdata macros */
                    461: #if LINUX_VERSION_CODE >= 0x020126
                    462: #include <linux/init.h>
                    463: #else
                    464: #define __initfunc(A) A
                    465: #define __initdata
                    466: #define __init
                    467: #endif
                    468: 
                    469: /* /proc support */
                    470: #if LINUX_VERSION_CODE >= 0x010300
                    471: #include <linux/stat.h> 
                    472: struct proc_dir_entry proc_scsi_gdth = {
                    473:     PROC_SCSI_GDTH, 4, "gdth",
                    474:     S_IFDIR | S_IRUGO | S_IXUGO, 2
                    475: };
                    476: #include "gdth_proc.h"
                    477: #include "gdth_proc.c"
                    478: #endif
                    479: 
                    480: #if LINUX_VERSION_CODE >= 0x020100
                    481: /* notifier block to get a notify on system shutdown/halt/reboot */
                    482: static struct notifier_block gdth_notifier = {
                    483:     gdth_halt, NULL, 0
                    484: };
                    485: #endif
                    486: 
                    487: static void gdth_delay(int milliseconds)
                    488: {
                    489:     if (milliseconds == 0) {
                    490:         udelay(1);
                    491:     } else {
                    492: #if LINUX_VERSION_CODE >= 0x020168
                    493:         mdelay(milliseconds);
                    494: #else
                    495:         int i;
                    496:         for (i = 0; i < milliseconds; ++i) 
                    497:             udelay(1000);
                    498: #endif
                    499:     }
                    500: }
                    501: 
                    502: /* controller search and initialization functions */
                    503: 
                    504: __initfunc (static int gdth_search_eisa(ushort eisa_adr))
                    505: {
                    506:     ulong id;
                    507:     
                    508:     TRACE(("gdth_search_eisa() adr. %x\n",eisa_adr));
                    509:     id = inl(eisa_adr+ID0REG);
                    510:     if (id == GDT3A_ID || id == GDT3B_ID) {     /* GDT3000A or GDT3000B */
                    511:         if ((inb(eisa_adr+EISAREG) & 8) == 0)   
                    512:             return 0;                           /* not EISA configured */
                    513:         return 1;
                    514:     }
                    515:     if (id == GDT3_ID)                          /* GDT3000 */
                    516:         return 1;
                    517: 
                    518:     return 0;                                   
                    519: }
                    520: 
                    521: 
                    522: __initfunc (static int gdth_search_isa(ulong bios_adr))
                    523: {
                    524:     void *addr;
                    525:     ulong id;
                    526: 
                    527:     TRACE(("gdth_search_isa() bios adr. %lx\n",bios_adr));
                    528:     if ((addr = gdth_mmap(bios_adr+BIOS_ID_OFFS, sizeof(ulong))) != NULL) {
                    529:        id = readl(addr);
                    530:        gdth_munmap(addr);
                    531:        if (id == GDT2_ID)                          /* GDT2000 */
                    532:            return 1;
                    533:     }
                    534:     return 0;
                    535: }
                    536: 
                    537: 
                    538: __initfunc (static int gdth_search_pci(ushort device_id,ushort index,gdth_pci_str *pcistr))
                    539: {
                    540:     int error;
                    541:     ulong base0,base1,base2;
                    542: 
                    543:     TRACE(("gdth_search_pci() device_id %d, index %d\n",
                    544:                  device_id,index));
                    545: 
                    546: #if LINUX_VERSION_CODE >= 0x20155
                    547:     if (!pci_present())
                    548:         return 0;
                    549: #else
                    550:     if (!pcibios_present())
                    551:         return 0;
                    552: #endif
                    553: 
                    554:     if (pcibios_find_device(PCI_VENDOR_ID_VORTEX,device_id,index,
                    555:                              &pcistr->bus,&pcistr->device_fn))
                    556:         return 0;
                    557: 
                    558:     /* GDT PCI controller found, now read resources from config space */
                    559: #if LINUX_VERSION_CODE >= 0x20155
                    560:     {
                    561:        struct pci_dev *pdev = pci_find_slot(pcistr->bus, pcistr->device_fn);
                    562:        base0 = pdev->base_address[0];
                    563:        base1 = pdev->base_address[1];
                    564:        base2 = pdev->base_address[2];
                    565:        if ((error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
                    566:                                               PCI_ROM_ADDRESS,
                    567:                                               (int *) &pcistr->bios))) {
                    568:            printk("GDT-PCI: error %d reading configuration space", error);
                    569:            return -1;
                    570:        }
                    571:        pcistr->irq = pdev->irq;
                    572:     }
                    573: #else
                    574: #if LINUX_VERSION_CODE >= 0x010300
                    575: #define GDTH_BASEP      (int *)
                    576: #else
                    577: #define GDTH_BASEP
                    578: #endif
                    579:     if ((error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
                    580:                                            PCI_BASE_ADDRESS_0,
                    581:                                            GDTH_BASEP&base0)) ||
                    582:         (error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
                    583:                                            PCI_BASE_ADDRESS_1,
                    584:                                            GDTH_BASEP&base1)) ||
                    585:         (error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
                    586:                                            PCI_BASE_ADDRESS_2,
                    587:                                            GDTH_BASEP&base2)) ||
                    588:         (error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
                    589:                                            PCI_ROM_ADDRESS,
                    590:                                            GDTH_BASEP&pcistr->bios)) ||
                    591:         (error = pcibios_read_config_byte(pcistr->bus,pcistr->device_fn,
                    592:                                           PCI_INTERRUPT_LINE,&pcistr->irq))) {
                    593:         printk("GDT-PCI: error %d reading configuration space", error);
                    594:         return -1;
                    595:     }
                    596: #endif
                    597: 
                    598:     pcistr->device_id = device_id;
                    599:     if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B ||   /* GDT6000 or GDT6000B */
                    600:         device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) {  /* MPR */
                    601:         if ((base0 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_MEMORY)
                    602:             return -1;
                    603:         pcistr->dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK;
                    604:     } else {                                    /* GDT6110, GDT6120, .. */
                    605:         if ((base0 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_MEMORY ||
                    606:             (base2 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_MEMORY ||
                    607:             (base1 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_IO)
                    608:             return -1;
                    609:         pcistr->dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK;
                    610:         pcistr->io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK;
                    611:         pcistr->io    = base1 & PCI_BASE_ADDRESS_IO_MASK;
                    612:     }
                    613:     return 1;
                    614: }
                    615: 
                    616: 
                    617: __initfunc (static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha))
                    618: {
                    619:     ulong retries,id;
                    620:     unchar prot_ver,eisacf,i,irq_found;
                    621: 
                    622:     TRACE(("gdth_init_eisa() adr. %x\n",eisa_adr));
                    623:     
                    624:     /* disable board interrupts, deinitialize services */
                    625:     outb(0xff,eisa_adr+EDOORREG);
                    626:     outb(0x00,eisa_adr+EDENABREG);
                    627:     outb(0x00,eisa_adr+EINTENABREG);
                    628:     
                    629:     outb(0xff,eisa_adr+LDOORREG);
                    630:     retries = INIT_RETRIES;
                    631:     gdth_delay(20);
                    632:     while (inb(eisa_adr+EDOORREG) != 0xff) {
                    633:         if (--retries == 0) {
                    634:             printk("GDT-EISA: Initialization error (DEINIT failed)\n");
                    635:             return 0;
                    636:         }
                    637:         gdth_delay(1);
                    638:         TRACE2(("wait for DEINIT: retries=%ld\n",retries));
                    639:     }
                    640:     prot_ver = inb(eisa_adr+MAILBOXREG);
                    641:     outb(0xff,eisa_adr+EDOORREG);
                    642:     if (prot_ver != PROTOCOL_VERSION) {
                    643:         printk("GDT-EISA: Illegal protocol version\n");
                    644:         return 0;
                    645:     }
                    646:     ha->bmic = eisa_adr;
                    647:     ha->brd_phys = (ulong)eisa_adr >> 12;
                    648: 
                    649:     outl(0,eisa_adr+MAILBOXREG);
                    650:     outl(0,eisa_adr+MAILBOXREG+4);
                    651:     outl(0,eisa_adr+MAILBOXREG+8);
                    652:     outl(0,eisa_adr+MAILBOXREG+12);
                    653: 
                    654:     /* detect IRQ */ 
                    655:     if ((id = inl(eisa_adr+ID0REG)) == GDT3_ID) {
                    656:         ha->type = GDT_EISA;
                    657:         ha->stype = id;
                    658:         outl(1,eisa_adr+MAILBOXREG+8);
                    659:         outb(0xfe,eisa_adr+LDOORREG);
                    660:         retries = INIT_RETRIES;
                    661:         gdth_delay(20);
                    662:         while (inb(eisa_adr+EDOORREG) != 0xfe) {
                    663:             if (--retries == 0) {
                    664:                 printk("GDT-EISA: Initialization error (get IRQ failed)\n");
                    665:                 return 0;
                    666:             }
                    667:             gdth_delay(1);
                    668:         }
                    669:         ha->irq = inb(eisa_adr+MAILBOXREG);
                    670:         outb(0xff,eisa_adr+EDOORREG);
                    671:         TRACE2(("GDT3000/3020: IRQ=%d\n",ha->irq));
                    672:        /* check the result */
                    673:        if (ha->irq == 0) {
                    674:            TRACE2(("Unknown IRQ, check IRQ table from cmd line !\n"));
                    675:            for (i=0,irq_found=FALSE; i<MAXHA && irqs[i]!=0xff; ++i) {
                    676:                if (irqs[i]!=0) {
                    677:                    irq_found=TRUE;
                    678:                    break;
                    679:                }
                    680:            }
                    681:            if (irq_found) {
                    682:                ha->irq = irqs[i];
                    683:                irqs[i] = 0;
                    684:                printk("GDT-EISA: Can not detect controller IRQ,\n");
                    685:                printk("Use IRQ setting from command line (IRQ = %d)\n",
                    686:                       ha->irq);
                    687:            } else {
                    688:                printk("GDT-EISA: Initialization error (unknown IRQ), Enable\n");
                    689:                printk("the controller BIOS or use command line parameters\n");
                    690:                return 0;
                    691:            }
                    692:        }
                    693:     } else {
                    694:         eisacf = inb(eisa_adr+EISAREG) & 7;
                    695:         if (eisacf > 4)                         /* level triggered */
                    696:             eisacf -= 4;
                    697:         ha->irq = gdth_irq_tab[eisacf];
                    698:         ha->type = GDT_EISA;
                    699:         ha->stype= id;
                    700:     }
                    701:     return 1;
                    702: }
                    703: 
                    704:        
                    705: __initfunc (static int gdth_init_isa(ulong bios_adr,gdth_ha_str *ha))
                    706: {
                    707:     register gdt2_dpram_str *dp2_ptr;
                    708:     int i;
                    709:     unchar irq_drq,prot_ver;
                    710:     ulong retries;
                    711: 
                    712:     TRACE(("gdth_init_isa() bios adr. %lx\n",bios_adr));
                    713: 
                    714:     ha->brd = gdth_mmap(bios_adr, sizeof(gdt2_dpram_str));
                    715:     if (ha->brd == NULL) {
                    716:        printk("GDT-ISA: Initialization error (DPMEM remap error)\n");
                    717:        return 0;
                    718:     }
                    719:     dp2_ptr = (gdt2_dpram_str *)ha->brd;
                    720:     writeb(1, &dp2_ptr->io.memlock);                   /* switch off write protection */
                    721:     /* reset interface area */
                    722:     memset_io((char *)&dp2_ptr->u,0,sizeof(dp2_ptr->u));
                    723:     if (readl(&dp2_ptr->u) != 0) {
                    724:        printk("GDT-PCI: Initialization error (DPMEM write error)\n");
                    725:        gdth_munmap(ha->brd);
                    726:        return 0;
                    727:     }
                    728: 
                    729:     /* disable board interrupts, read DRQ and IRQ */
                    730:     writeb(0xff, &dp2_ptr->io.irqdel);
                    731:     writeb(0x00, &dp2_ptr->io.irqen);
                    732:     writeb(0x00, &dp2_ptr->u.ic.S_Status);
                    733:     writeb(0x00, &dp2_ptr->u.ic.Cmd_Index);
                    734: 
                    735:     irq_drq = readb(&dp2_ptr->io.rq);
                    736:     for (i=0; i<3; ++i) {
                    737:         if ((irq_drq & 1)==0)
                    738:             break;
                    739:         irq_drq >>= 1;
                    740:     }
                    741:     ha->drq = gdth_drq_tab[i];
                    742: 
                    743:     irq_drq = readb(&dp2_ptr->io.rq) >> 3;
                    744:     for (i=1; i<5; ++i) {
                    745:         if ((irq_drq & 1)==0)
                    746:             break;
                    747:         irq_drq >>= 1;
                    748:     }
                    749:     ha->irq = gdth_irq_tab[i];
                    750: 
                    751:     /* deinitialize services */
                    752:     writel(bios_adr, &dp2_ptr->u.ic.S_Info[0]);
                    753:     writeb(0xff, &dp2_ptr->u.ic.S_Cmd_Indx);
                    754:     writeb(0, &dp2_ptr->io.event);
                    755:     retries = INIT_RETRIES;
                    756:     gdth_delay(20);
                    757:     while (readb(&dp2_ptr->u.ic.S_Status) != 0xff) {
                    758:         if (--retries == 0) {
                    759:             printk("GDT-ISA: Initialization error (DEINIT failed)\n");
                    760:            gdth_munmap(ha->brd);
                    761:             return 0;
                    762:         }
                    763:         gdth_delay(1);
                    764:     }
                    765:     prot_ver = (unchar)readl(&dp2_ptr->u.ic.S_Info[0]);
                    766:     writeb(0, &dp2_ptr->u.ic.Status);
                    767:     writeb(0xff, &dp2_ptr->io.irqdel);
                    768:     if (prot_ver != PROTOCOL_VERSION) {
                    769:         printk("GDT-ISA: Illegal protocol version\n");
                    770:        gdth_munmap(ha->brd);
                    771:         return 0;
                    772:     }
                    773: 
                    774:     ha->type = GDT_ISA;
                    775:     ha->ic_all_size = sizeof(dp2_ptr->u);
                    776:     ha->stype= GDT2_ID;
                    777:     ha->brd_phys = bios_adr >> 4;
                    778: 
                    779:     /* special request to controller BIOS */
                    780:     writel(0x00, &dp2_ptr->u.ic.S_Info[0]);
                    781:     writel(0x00, &dp2_ptr->u.ic.S_Info[1]);
                    782:     writel(0x01, &dp2_ptr->u.ic.S_Info[2]);
                    783:     writel(0x00, &dp2_ptr->u.ic.S_Info[3]);
                    784:     writeb(0xfe, &dp2_ptr->u.ic.S_Cmd_Indx);
                    785:     writeb(0, &dp2_ptr->io.event);
                    786:     retries = INIT_RETRIES;
                    787:     gdth_delay(20);
                    788:     while (readb(&dp2_ptr->u.ic.S_Status) != 0xfe) {
                    789:         if (--retries == 0) {
                    790:             printk("GDT-ISA: Initialization error\n");
                    791:            gdth_munmap(ha->brd);
                    792:             return 0;
                    793:         }
                    794:         gdth_delay(1);
                    795:     }
                    796:     writeb(0, &dp2_ptr->u.ic.Status);
                    797:     writeb(0xff, &dp2_ptr->io.irqdel);
                    798:     return 1;
                    799: }
                    800: 
                    801: 
                    802: __initfunc (static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
                    803: {
                    804:     register gdt6_dpram_str *dp6_ptr;
                    805:     register gdt6c_dpram_str *dp6c_ptr;
                    806:     register gdt6m_dpram_str *dp6m_ptr;
                    807:     ulong retries;
                    808:     unchar prot_ver;
                    809:     int i, found = FALSE;
                    810: 
                    811:     TRACE(("gdth_init_pci()\n"));
                    812: 
                    813:     ha->brd_phys = (pcistr->bus << 8) | (pcistr->device_fn & 0xf8);
                    814:     ha->stype    = (ulong)pcistr->device_id;
                    815:     ha->irq      = pcistr->irq;
                    816:     
                    817:     if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) {   /* GDT6000 or GDT6000B */
                    818:         TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
                    819:        ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6_dpram_str));
                    820:        if (ha->brd == NULL) {
                    821:            printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                    822:            return 0;
                    823:        }
                    824:         dp6_ptr = (gdt6_dpram_str *)ha->brd;
                    825:         /* reset interface area */
                    826:         memset_io((char *)&dp6_ptr->u,0,sizeof(dp6_ptr->u));
                    827:         if (readl(&dp6_ptr->u) != 0) {
                    828:             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
                    829:            gdth_munmap(ha->brd);
                    830:             return 0;
                    831:         }
                    832:         
                    833:         /* disable board interrupts, deinit services */
                    834:         writeb(0xff, &dp6_ptr->io.irqdel);
                    835:         writeb(0x00, &dp6_ptr->io.irqen);;
                    836:         writeb(0x00, &dp6_ptr->u.ic.S_Status);
                    837:         writeb(0x00, &dp6_ptr->u.ic.Cmd_Index);
                    838: 
                    839:         writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]);
                    840:         writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx);
                    841:         writeb(0, &dp6_ptr->io.event);
                    842:         retries = INIT_RETRIES;
                    843:         gdth_delay(20);
                    844:         while (readb(&dp6_ptr->u.ic.S_Status) != 0xff) {
                    845:             if (--retries == 0) {
                    846:                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
                    847:                gdth_munmap(ha->brd);
                    848:                 return 0;
                    849:             }
                    850:             gdth_delay(1);
                    851:         }
                    852:         prot_ver = (unchar)readl(&dp6_ptr->u.ic.S_Info[0]);
                    853:         writeb(0, &dp6_ptr->u.ic.S_Status);
                    854:         writeb(0xff, &dp6_ptr->io.irqdel);
                    855:         if (prot_ver != PROTOCOL_VERSION) {
                    856:             printk("GDT-PCI: Illegal protocol version\n");
                    857:            gdth_munmap(ha->brd);
                    858:             return 0;
                    859:         }
                    860: 
                    861:         ha->type = GDT_PCI;
                    862:         ha->ic_all_size = sizeof(dp6_ptr->u);
                    863:         
                    864:         /* special command to controller BIOS */
                    865:         writel(0x00, &dp6_ptr->u.ic.S_Info[0]);
                    866:         writel(0x00, &dp6_ptr->u.ic.S_Info[1]);
                    867:         writel(0x01, &dp6_ptr->u.ic.S_Info[2]);
                    868:         writel(0x00, &dp6_ptr->u.ic.S_Info[3]);
                    869:         writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx);
                    870:         writeb(0, &dp6_ptr->io.event);
                    871:         retries = INIT_RETRIES;
                    872:         gdth_delay(20);
                    873:         while (readb(&dp6_ptr->u.ic.S_Status) != 0xfe) {
                    874:             if (--retries == 0) {
                    875:                 printk("GDT-PCI: Initialization error\n");
                    876:                gdth_munmap(ha->brd);
                    877:                 return 0;
                    878:             }
                    879:             gdth_delay(1);
                    880:         }
                    881:         writeb(0, &dp6_ptr->u.ic.S_Status);
                    882:         writeb(0xff, &dp6_ptr->io.irqdel);
                    883: 
                    884:     } else if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6555) { /* GDT6110, GDT6120, .. */
                    885:        ha->plx = (gdt6c_plx_regs *)pcistr->io;
                    886:        TRACE2(("init_pci_new() dpmem %lx io %lx irq %d\n",
                    887:                pcistr->dpmem,(ulong)ha->plx,ha->irq));
                    888:        ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6c_dpram_str));
                    889:        if (ha->brd == NULL) {
                    890:            printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                    891:            gdth_munmap(ha->brd);
                    892:            return 0;
                    893:        }
                    894:         dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
                    895:         /* reset interface area */
                    896:         memset_io((char *)&dp6c_ptr->u,0,sizeof(dp6c_ptr->u));
                    897:         if (readl(&dp6c_ptr->u) != 0) {
                    898:             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
                    899:            gdth_munmap(ha->brd);
                    900:             return 0;
                    901:         }
                    902:         
                    903:         /* disable board interrupts, deinit services */
                    904:         outb(0x00,PTR2USHORT(&ha->plx->control1));
                    905:         outb(0xff,PTR2USHORT(&ha->plx->edoor_reg));
                    906:         
                    907:         writeb(0x00, &dp6c_ptr->u.ic.S_Status);
                    908:         writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index);
                    909: 
                    910:         writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]);
                    911:         writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx);
                    912: 
                    913:         outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
                    914: 
                    915:         retries = INIT_RETRIES;
                    916:         gdth_delay(20);
                    917:         while (readb(&dp6c_ptr->u.ic.S_Status) != 0xff) {
                    918:             if (--retries == 0) {
                    919:                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
                    920:                gdth_munmap(ha->brd);
                    921:                 return 0;
                    922:             }
                    923:             gdth_delay(1);
                    924:         }
                    925:         prot_ver = (unchar)readl(&dp6c_ptr->u.ic.S_Info[0]);
                    926:         writeb(0, &dp6c_ptr->u.ic.Status);
                    927:         if (prot_ver != PROTOCOL_VERSION) {
                    928:             printk("GDT-PCI: Illegal protocol version\n");
                    929:            gdth_munmap(ha->brd);
                    930:             return 0;
                    931:         }
                    932: 
                    933:         ha->type = GDT_PCINEW;
                    934:         ha->ic_all_size = sizeof(dp6c_ptr->u);
                    935: 
                    936:         /* special command to controller BIOS */
                    937:         writel(0x00, &dp6c_ptr->u.ic.S_Info[0]);
                    938:         writel(0x00, &dp6c_ptr->u.ic.S_Info[1]);
                    939:         writel(0x01, &dp6c_ptr->u.ic.S_Info[2]);
                    940:         writel(0x00, &dp6c_ptr->u.ic.S_Info[3]);
                    941:         writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx);
                    942:         
                    943:         outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
                    944: 
                    945:         retries = INIT_RETRIES;
                    946:         gdth_delay(20);
                    947:         while (readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) {
                    948:             if (--retries == 0) {
                    949:                 printk("GDT-PCI: Initialization error\n");
                    950:                gdth_munmap(ha->brd);
                    951:                 return 0;
                    952:             }
                    953:             gdth_delay(1);
                    954:         }
                    955:         writeb(0, &dp6c_ptr->u.ic.S_Status);
                    956: 
                    957:     } else {                                            /* MPR */
                    958:        TRACE2(("init_pci_mpr() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
                    959:        ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6m_dpram_str));
                    960:        if (ha->brd == NULL) {
                    961:            printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                    962:            return 0;
                    963:        }
                    964: 
                    965:         /* check and reset interface area */
                    966:         dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
                    967:        writel(DPMEM_MAGIC, &dp6m_ptr->u);
                    968:        if (readl(&dp6m_ptr->u) != DPMEM_MAGIC) {
                    969:            printk("GDT-PCI: Cannot access DPMEM at 0x%x (shadowed?)\n", 
                    970:                   (int)ha->brd);
                    971:            found = FALSE;
                    972:            for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
                    973:                pcibios_write_config_dword( pcistr->bus, pcistr->device_fn,
                    974:                                            PCI_BASE_ADDRESS_0, i );
                    975:                gdth_munmap( ha->brd );
                    976:                ha->brd = gdth_mmap(i, sizeof(gdt6m_dpram_str)); 
                    977:                if (ha->brd == NULL) {
                    978:                    printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                    979:                    return 0;
                    980:                }
                    981:                dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
                    982:                writel(DPMEM_MAGIC, &dp6m_ptr->u);
                    983:                if (readl(&dp6m_ptr->u) == DPMEM_MAGIC) {
                    984:                    printk("GDT-PCI: Use free address at 0x%x\n",
                    985:                           (int)ha->brd);
                    986:                    found = TRUE;
                    987:                    break;
                    988:                }
                    989:            }   
                    990:            if (!found) {
                    991:                printk("GDT-PCI: No free address found!\n");
                    992:                gdth_munmap( ha->brd );
                    993:                return 0;
                    994:            }
                    995:        }
                    996:         memset_io((char *)&dp6m_ptr->u,0,sizeof(dp6m_ptr->u));
                    997:         
                    998:         /* disable board interrupts, deinit services */
                    999:         writeb(readb(&dp6m_ptr->i960r.edoor_en_reg) | 4,
                   1000:               &dp6m_ptr->i960r.edoor_en_reg);
                   1001:         writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
                   1002:         writeb(0x00, &dp6m_ptr->u.ic.S_Status);
                   1003:         writeb(0x00, &dp6m_ptr->u.ic.Cmd_Index);
                   1004: 
                   1005:         writel(pcistr->dpmem, &dp6m_ptr->u.ic.S_Info[0]);
                   1006:         writeb(0xff, &dp6m_ptr->u.ic.S_Cmd_Indx);
                   1007:         writeb(1, &dp6m_ptr->i960r.ldoor_reg);
                   1008:         retries = INIT_RETRIES;
                   1009:         gdth_delay(20);
                   1010:         while (readb(&dp6m_ptr->u.ic.S_Status) != 0xff) {
                   1011:             if (--retries == 0) {
                   1012:                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
                   1013:                gdth_munmap(ha->brd);
                   1014:                 return 0;
                   1015:             }
                   1016:             gdth_delay(1);
                   1017:         }
                   1018:         prot_ver = (unchar)readl(&dp6m_ptr->u.ic.S_Info[0]);
                   1019:         writeb(0, &dp6m_ptr->u.ic.S_Status);
                   1020:         if (prot_ver != PROTOCOL_VERSION) {
                   1021:             printk("GDT-PCI: Illegal protocol version\n");
                   1022:            gdth_munmap(ha->brd);
                   1023:             return 0;
                   1024:         }
                   1025: 
                   1026:         ha->type = GDT_PCIMPR;
                   1027:         ha->ic_all_size = sizeof(dp6m_ptr->u);
                   1028:         
                   1029:         /* special command to controller BIOS */
                   1030:         writel(0x00, &dp6m_ptr->u.ic.S_Info[0]);
                   1031:         writel(0x00, &dp6m_ptr->u.ic.S_Info[1]);
                   1032:         writel(0x01, &dp6m_ptr->u.ic.S_Info[2]);
                   1033:         writel(0x00, &dp6m_ptr->u.ic.S_Info[3]);
                   1034:         writeb(0xfe, &dp6m_ptr->u.ic.S_Cmd_Indx);
                   1035:         writeb(1, &dp6m_ptr->i960r.ldoor_reg);
                   1036:         retries = INIT_RETRIES;
                   1037:         gdth_delay(20);
                   1038:         while (readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) {
                   1039:             if (--retries == 0) {
                   1040:                 printk("GDT-PCI: Initialization error\n");
                   1041:                gdth_munmap(ha->brd);
                   1042:                 return 0;
                   1043:             }
                   1044:             gdth_delay(1);
                   1045:         }
                   1046:         writeb(0, &dp6m_ptr->u.ic.S_Status);
                   1047:     }
                   1048: 
                   1049:     return 1;
                   1050: }
                   1051: 
                   1052: 
                   1053: /* controller protocol functions */
                   1054: 
                   1055: __initfunc (static void gdth_enable_int(int hanum))
                   1056: {
                   1057:     gdth_ha_str *ha;
                   1058:     ulong flags;
                   1059:     gdt2_dpram_str *dp2_ptr;
                   1060:     gdt6_dpram_str *dp6_ptr;
                   1061:     gdt6m_dpram_str *dp6m_ptr;
                   1062: 
                   1063:     TRACE(("gdth_enable_int() hanum %d\n",hanum));
                   1064:     ha = HADATA(gdth_ctr_tab[hanum]);
                   1065: 
                   1066:     save_flags(flags);
                   1067:     cli();
                   1068: 
                   1069:     if (ha->type == GDT_EISA) {
                   1070:         outb(0xff, ha->bmic + EDOORREG);
                   1071:         outb(0xff, ha->bmic + EDENABREG);
                   1072:         outb(0x01, ha->bmic + EINTENABREG);
                   1073:     } else if (ha->type == GDT_ISA) {
                   1074:         dp2_ptr = (gdt2_dpram_str *)ha->brd;
                   1075:         writeb(1, &dp2_ptr->io.irqdel);
                   1076:         writeb(0, &dp2_ptr->u.ic.Cmd_Index);
                   1077:         writeb(1, &dp2_ptr->io.irqen);
                   1078:     } else if (ha->type == GDT_PCI) {
                   1079:         dp6_ptr = (gdt6_dpram_str *)ha->brd;
                   1080:         writeb(1, &dp6_ptr->io.irqdel);
                   1081:         writeb(0, &dp6_ptr->u.ic.Cmd_Index);
                   1082:         writeb(1, &dp6_ptr->io.irqen);
                   1083:     } else if (ha->type == GDT_PCINEW) {
                   1084:         outb(0xff, PTR2USHORT(&ha->plx->edoor_reg));
                   1085:         outb(0x03, PTR2USHORT(&ha->plx->control1));
                   1086:     } else if (ha->type == GDT_PCIMPR) {
                   1087:         dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
                   1088:         writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
                   1089:         writeb(readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4,
                   1090:               &dp6m_ptr->i960r.edoor_en_reg);
                   1091:     }
                   1092:     restore_flags(flags);
                   1093: }
                   1094: 
                   1095: 
                   1096: static int gdth_get_status(unchar *pIStatus,int irq)
                   1097: {
                   1098:     register gdth_ha_str *ha;
                   1099:     int i;
                   1100: 
                   1101:     TRACE(("gdth_get_status() irq %d ctr_count %d\n",
                   1102:                  irq,gdth_ctr_count));
                   1103:     
                   1104:     *pIStatus = 0;
                   1105:     for (i=0; i<gdth_ctr_count; ++i) {
                   1106:         ha = HADATA(gdth_ctr_tab[i]);
                   1107:         if (ha->irq != (unchar)irq)             /* check IRQ */
                   1108:             continue;
                   1109:         if (ha->type == GDT_EISA)
                   1110:             *pIStatus = inb((ushort)ha->bmic + EDOORREG);
                   1111:         else if (ha->type == GDT_ISA)
                   1112:             *pIStatus = readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Cmd_Index);
                   1113:         else if (ha->type == GDT_PCI)
                   1114:             *pIStatus = readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Cmd_Index);
                   1115:         else if (ha->type == GDT_PCINEW) 
                   1116:             *pIStatus = inb(PTR2USHORT(&ha->plx->edoor_reg));
                   1117:         else if (ha->type == GDT_PCIMPR)
                   1118:             *pIStatus = readb(&((gdt6m_dpram_str *)ha->brd)->i960r.edoor_reg);
                   1119:    
                   1120:         if (*pIStatus)                                  
                   1121:             return i;                           /* board found */
                   1122:     }
                   1123:     return -1;
                   1124: }
                   1125:                  
                   1126:     
                   1127: static int gdth_test_busy(int hanum)
                   1128: {
                   1129:     register gdth_ha_str *ha;
                   1130:     register int gdtsema0 = 0;
                   1131: 
                   1132:     TRACE(("gdth_test_busy() hanum %d\n",hanum));
                   1133:     
                   1134:     ha = HADATA(gdth_ctr_tab[hanum]);
                   1135:     if (ha->type == GDT_EISA)
                   1136:         gdtsema0 = (int)inb(ha->bmic + SEMA0REG);
                   1137:     else if (ha->type == GDT_ISA)
                   1138:         gdtsema0 = (int)readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
                   1139:     else if (ha->type == GDT_PCI)
                   1140:         gdtsema0 = (int)readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
                   1141:     else if (ha->type == GDT_PCINEW) 
                   1142:         gdtsema0 = (int)inb(PTR2USHORT(&ha->plx->sema0_reg));
                   1143:     else if (ha->type == GDT_PCIMPR)
                   1144:         gdtsema0 = (int)readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
                   1145: 
                   1146:     return (gdtsema0 & 1);
                   1147: }
                   1148: 
                   1149: 
                   1150: static int gdth_get_cmd_index(int hanum)
                   1151: {
                   1152:     register gdth_ha_str *ha;
                   1153:     int i;
                   1154: 
                   1155:     TRACE(("gdth_get_cmd_index() hanum %d\n",hanum));
                   1156: 
                   1157:     ha = HADATA(gdth_ctr_tab[hanum]);
                   1158:     for (i=0; i<GDTH_MAXCMDS; ++i) {
                   1159:         if (gdth_cmd_tab[i][hanum].cmnd == UNUSED_CMND) {
                   1160:             gdth_cmd_tab[i][hanum].cmnd = ha->pccb->RequestBuffer;
                   1161:             gdth_cmd_tab[i][hanum].service = ha->pccb->Service;
                   1162:             ha->pccb->CommandIndex = (ulong)i+2;
                   1163:             return (i+2);
                   1164:         }
                   1165:     }
                   1166:     return 0;
                   1167: }
                   1168: 
                   1169: 
                   1170: static void gdth_set_sema0(int hanum)
                   1171: {
                   1172:     register gdth_ha_str *ha;
                   1173: 
                   1174:     TRACE(("gdth_set_sema0() hanum %d\n",hanum));
                   1175: 
                   1176:     ha = HADATA(gdth_ctr_tab[hanum]);
                   1177:     if (ha->type == GDT_EISA)
                   1178:         outb(1, ha->bmic + SEMA0REG);
                   1179:     else if (ha->type == GDT_ISA)
                   1180:         writeb(1, &((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
                   1181:     else if (ha->type == GDT_PCI)
                   1182:         writeb(1, &((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
                   1183:     else if (ha->type == GDT_PCINEW)  
                   1184:         outb(1, PTR2USHORT(&ha->plx->sema0_reg));
                   1185:     else if (ha->type == GDT_PCIMPR)
                   1186:         writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
                   1187:     
                   1188: }
                   1189: 
                   1190: 
                   1191: static void gdth_copy_command(int hanum)
                   1192: {
                   1193:     register gdth_ha_str *ha;
                   1194:     register gdth_cmd_str *cmd_ptr;
                   1195:     register gdt6m_dpram_str *dp6m_ptr;
                   1196:     register gdt6c_dpram_str *dp6c_ptr;
                   1197:     gdt6_dpram_str *dp6_ptr;
                   1198:     gdt2_dpram_str *dp2_ptr;
                   1199:     ushort cp_count,dp_offset,cmd_no;
                   1200:     
                   1201:     TRACE(("gdth_copy_command() hanum %d\n",hanum));
                   1202: 
                   1203:     ha = HADATA(gdth_ctr_tab[hanum]);
                   1204:     cp_count = ha->cmd_len;
                   1205:     dp_offset= ha->cmd_offs_dpmem;
                   1206:     cmd_no   = ha->cmd_cnt;
                   1207:     cmd_ptr  = ha->pccb;
                   1208: 
                   1209:     ++ha->cmd_cnt;                                                      
                   1210:     if (ha->type == GDT_EISA)
                   1211:         return;                                 /* no DPMEM, no copy */
                   1212: 
                   1213:     /* set cpcount dword aligned */
                   1214:     if (cp_count & 3)
                   1215:         cp_count += (4 - (cp_count & 3));
                   1216: 
                   1217:     ha->cmd_offs_dpmem += cp_count;
                   1218:     
                   1219:     /* set offset and service, copy command to DPMEM */
                   1220:     if (ha->type == GDT_ISA) {
                   1221:         dp2_ptr = (gdt2_dpram_str *)ha->brd;
                   1222:         writew(dp_offset + DPMEM_COMMAND_OFFSET, 
                   1223:               &dp2_ptr->u.ic.comm_queue[cmd_no].offset);
                   1224:         writew((ushort)cmd_ptr->Service, 
                   1225:               &dp2_ptr->u.ic.comm_queue[cmd_no].serv_id);
                   1226:        memcpy_toio(&dp2_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
                   1227:     } else if (ha->type == GDT_PCI) {
                   1228:         dp6_ptr = (gdt6_dpram_str *)ha->brd;
                   1229:         writew(dp_offset + DPMEM_COMMAND_OFFSET, 
                   1230:               &dp6_ptr->u.ic.comm_queue[cmd_no].offset);
                   1231:         writew((ushort)cmd_ptr->Service, 
                   1232:               &dp6_ptr->u.ic.comm_queue[cmd_no].serv_id);
                   1233:         memcpy_toio(&dp6_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
                   1234:     } else if (ha->type == GDT_PCINEW) {
                   1235:         dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
                   1236:         writew(dp_offset + DPMEM_COMMAND_OFFSET, 
                   1237:               &dp6c_ptr->u.ic.comm_queue[cmd_no].offset);
                   1238:        writew((ushort)cmd_ptr->Service, 
                   1239:               &dp6c_ptr->u.ic.comm_queue[cmd_no].serv_id);
                   1240:        memcpy_toio(&dp6c_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
                   1241:     } else if (ha->type == GDT_PCIMPR) {
                   1242:         dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
                   1243:         writew(dp_offset + DPMEM_COMMAND_OFFSET, 
                   1244:               &dp6m_ptr->u.ic.comm_queue[cmd_no].offset);
                   1245:         writew((ushort)cmd_ptr->Service, 
                   1246:               &dp6m_ptr->u.ic.comm_queue[cmd_no].serv_id);
                   1247:         memcpy_toio(&dp6m_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
                   1248:     }
                   1249: }
                   1250: 
                   1251: 
                   1252: static void gdth_release_event(int hanum)
                   1253: {
                   1254:     register gdth_ha_str *ha;
                   1255: 
                   1256: #ifdef GDTH_STATISTICS
                   1257:     ulong i,j;
                   1258:     for (i=0,j=0; j<GDTH_MAXCMDS; ++j) {
                   1259:         if (gdth_cmd_tab[j][hanum].cmnd != UNUSED_CMND)
                   1260:             ++i;
                   1261:     }
                   1262:     if (max_index < i) {
                   1263:         max_index = i;
                   1264:         TRACE3(("GDT: max_index = %d\n",(ushort)i));
                   1265:     }
                   1266: #endif
                   1267: 
                   1268:     TRACE(("gdth_release_event() hanum %d\n",hanum));
                   1269:     ha = HADATA(gdth_ctr_tab[hanum]);
                   1270: 
                   1271:     if (ha->pccb->OpCode == GDT_INIT)
                   1272:         ha->pccb->Service |= 0x80;
                   1273: 
                   1274:     if (ha->type == GDT_EISA) {
                   1275:         outb(ha->pccb->Service, ha->bmic + LDOORREG);
                   1276:         if (ha->pccb->OpCode == GDT_INIT)               /* store DMA buffer */
                   1277:             outl((ulong)ha->pccb, ha->bmic + MAILBOXREG);
                   1278:     } else if (ha->type == GDT_ISA)
                   1279:         writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event);
                   1280:     else if (ha->type == GDT_PCI)
                   1281:         writeb(0, &((gdt6_dpram_str *)ha->brd)->io.event);
                   1282:     else if (ha->type == GDT_PCINEW) 
                   1283:         outb(1, PTR2USHORT(&ha->plx->ldoor_reg));
                   1284:     else if (ha->type == GDT_PCIMPR)
                   1285:         writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.ldoor_reg);
                   1286: }
                   1287: 
                   1288:     
                   1289: static int gdth_wait(int hanum,int index,ulong time)
                   1290: {
                   1291:     gdth_ha_str *ha;
                   1292:     int answer_found = FALSE;
                   1293: 
                   1294:     TRACE(("gdth_wait() hanum %d index %d time %ld\n",hanum,index,time));
                   1295: 
                   1296:     ha = HADATA(gdth_ctr_tab[hanum]);
                   1297:     if (index == 0)
                   1298:         return 1;                               /* no wait required */
                   1299: 
                   1300:     gdth_from_wait = TRUE;
                   1301:     do {
                   1302: #if LINUX_VERSION_CODE >= 0x010346
                   1303:         gdth_interrupt((int)ha->irq,NULL,NULL);
                   1304: #else
                   1305:         gdth_interrupt((int)ha->irq,NULL);
                   1306: #endif
                   1307:         if (wait_hanum==hanum && wait_index==index) {
                   1308:             answer_found = TRUE;
                   1309:             break;
                   1310:         }
                   1311:         gdth_delay(1);
                   1312:     } while (--time);
                   1313:     gdth_from_wait = FALSE;
                   1314:     
                   1315:     while (gdth_test_busy(hanum))
                   1316:         gdth_delay(0);
                   1317: 
                   1318:     return (answer_found);
                   1319: }
                   1320: 
                   1321: 
                   1322: static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong p1,
                   1323:                              ulong p2,ulong p3)
                   1324: {
                   1325:     register gdth_ha_str *ha;
                   1326:     register gdth_cmd_str *cmd_ptr;
                   1327:     int retries,index;
                   1328: 
                   1329:     TRACE2(("gdth_internal_cmd() service %d opcode %d\n",service,opcode));
                   1330: 
                   1331:     ha = HADATA(gdth_ctr_tab[hanum]);
                   1332:     cmd_ptr = ha->pccb;
                   1333:     memset((char*)cmd_ptr,0,sizeof(gdth_cmd_str));
                   1334: 
                   1335:     /* make command  */
                   1336:     for (retries = INIT_RETRIES;;) {
                   1337:         cmd_ptr->Service          = service;
                   1338:         cmd_ptr->RequestBuffer    = INTERNAL_CMND;
                   1339:         if (!(index=gdth_get_cmd_index(hanum))) {
                   1340:             TRACE(("GDT: No free command index found\n"));
                   1341:             return 0;
                   1342:         }
                   1343:         gdth_set_sema0(hanum);
                   1344:         cmd_ptr->OpCode           = opcode;
                   1345:         cmd_ptr->BoardNode        = LOCALBOARD;
                   1346:         if (service == CACHESERVICE) {
                   1347:             if (opcode == GDT_IOCTL) {
                   1348:                 cmd_ptr->u.ioctl.subfunc = p1;
                   1349:                 cmd_ptr->u.ioctl.channel = p2;
                   1350:                 cmd_ptr->u.ioctl.param_size = (ushort)p3;
                   1351:                 cmd_ptr->u.ioctl.p_param = virt_to_bus(ha->pscratch);
                   1352:             } else {
                   1353:                 cmd_ptr->u.cache.DeviceNo = (ushort)p1;
                   1354:                 cmd_ptr->u.cache.BlockNo  = p2;
                   1355:             }
                   1356:         } else if (service == SCSIRAWSERVICE) {
                   1357:             cmd_ptr->u.raw.direction  = p1;
                   1358:             cmd_ptr->u.raw.bus        = (unchar)p2;
                   1359:             cmd_ptr->u.raw.target     = (unchar)p3;
                   1360:             cmd_ptr->u.raw.lun        = 0;
                   1361:         }
                   1362:         ha->cmd_len          = sizeof(gdth_cmd_str);
                   1363:         ha->cmd_offs_dpmem   = 0;
                   1364:         ha->cmd_cnt          = 0;
                   1365:         gdth_copy_command(hanum);
                   1366:         gdth_release_event(hanum);
                   1367:         gdth_delay(20);
                   1368:         if (!gdth_wait(hanum,index,INIT_TIMEOUT)) {
                   1369:             printk("GDT: Initialization error (timeout service %d)\n",service);
                   1370:             return 0;
                   1371:         }
                   1372:         if (ha->status != S_BSY || --retries == 0)
                   1373:             break;
                   1374:         gdth_delay(1);   
                   1375:     }   
                   1376:     
                   1377:     return (ha->status != S_OK ? 0:1);
                   1378: }
                   1379:     
                   1380: 
                   1381: /* search for devices */
                   1382: 
                   1383: __initfunc (static int gdth_search_drives(int hanum))
                   1384: {
                   1385:     register gdth_ha_str *ha;
                   1386:     ushort cdev_cnt,i;
                   1387:     unchar b,t,pos_found;
                   1388:     ulong drv_cyls, drv_hds, drv_secs;
                   1389:     ulong bus_no;
                   1390:     gdth_getch_str *chn;
                   1391:     gdth_iochan_str *ioc;
                   1392:     
                   1393:     TRACE(("gdth_search_drives() hanum %d\n",hanum));
                   1394:     ha = HADATA(gdth_ctr_tab[hanum]);
                   1395: 
                   1396:     /* initialize controller services, at first: screen service */
                   1397:     if (!gdth_internal_cmd(hanum,SCREENSERVICE,GDT_INIT,0,0,0)) {
                   1398:         printk("GDT: Initialization error screen service (code %d)\n",
                   1399:                ha->status);
                   1400:         return 0;
                   1401:     }
                   1402:     TRACE2(("gdth_search_drives(): SCREENSERVICE initialized\n"));
                   1403:     
                   1404:     /* initialize cache service */
                   1405:     if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0)) {
                   1406:         printk("GDT: Initialization error cache service (code %d)\n",
                   1407:                ha->status);
                   1408:         return 0;
                   1409:     }
                   1410:     TRACE2(("gdth_search_drives(): CACHESERVICE initialized\n"));
                   1411:     cdev_cnt = (ushort)ha->info;
                   1412: 
                   1413:     /* mount all cache devices */
                   1414:     gdth_internal_cmd(hanum,CACHESERVICE,GDT_MOUNT,0xffff,1,0);
                   1415:     TRACE2(("gdth_search_drives(): mountall CACHESERVICE OK\n"));
                   1416: 
                   1417:     /* initialize cache service after mountall */
                   1418:     if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0)) {
                   1419:        printk("GDT: Initialization error cache service (code %d)\n",
                   1420:               ha->status);
                   1421:        return 0;
                   1422:     }
                   1423:     TRACE2(("gdth_search_drives() CACHES. init. after mountall\n"));
                   1424:     cdev_cnt = (ushort)ha->info;
                   1425: 
                   1426:     /* detect number of SCSI buses - try new IOCTL */
                   1427:     ioc = (gdth_iochan_str *)DMADATA(gdth_ctr_tab[hanum]);
                   1428:     ioc->version       = -1UL;
                   1429:     ioc->list_entries  = MAXBUS;
                   1430:     ioc->first_chan    = 0;
                   1431:     ioc->last_chan     = MAXBUS-1;
                   1432:     ioc->list_offset   = GDTOFFSOF(gdth_iochan_str, list[0]);
                   1433:     if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,GET_IOCHAN_DESC,
                   1434:                          INVALID_CHANNEL,sizeof(gdth_iochan_str))) {
                   1435:        TRACE2(("GET_IOCHAN_DESC supported!\n"));
                   1436:        ha->bus_cnt = ioc->chan_count;
                   1437:        for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no)
                   1438:            if (ioc->list[bus_no].proc_id < MAXID)
                   1439:                ha->id[bus_no][ioc->list[bus_no].proc_id].type = SIOP_DTYP;
                   1440:     } else {
                   1441:        /* old method */
                   1442:        chn = (gdth_getch_str *)DMADATA(gdth_ctr_tab[hanum]);
                   1443:        for (bus_no = 0; bus_no < MAXBUS; ++bus_no) {
                   1444:            chn->channel_no = bus_no;
                   1445:            if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
                   1446:                                   SCSI_CHAN_CNT | L_CTRL_PATTERN,
                   1447:                                   IO_CHANNEL | INVALID_CHANNEL,
                   1448:                                   sizeof(gdth_getch_str))) {
                   1449:                if (bus_no == 0) {
                   1450:                    printk("GDT: Error detecting SCSI channel count (0x%x)\n",
                   1451:                           ha->status);
                   1452:                    return 0;
                   1453:                }
                   1454:                break;
                   1455:            }
                   1456:            if (chn->siop_id < MAXID)
                   1457:                ha->id[bus_no][chn->siop_id].type = SIOP_DTYP;
                   1458:        }       
                   1459:        ha->bus_cnt = (unchar)bus_no;
                   1460:     }
                   1461:     TRACE2(("gdth_search_drives() %d SCSI channels\n",ha->bus_cnt));
                   1462: 
                   1463:     /* read cache configuration */
                   1464:     if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_INFO,
                   1465:                           INVALID_CHANNEL,sizeof(gdth_cinfo_str))) {
                   1466:        printk("GDT: Initialization error cache service (code %d)\n",
                   1467:               ha->status);
                   1468:        return 0;
                   1469:     }
                   1470:     ha->cpar = ((gdth_cinfo_str *)DMADATA(gdth_ctr_tab[hanum]))->cpar;
                   1471:     TRACE2(("gdth_search_drives() cinfo: vs %lx sta %d str %d dw %d b %d\n",
                   1472:            ha->cpar.version,ha->cpar.state,ha->cpar.strategy,
                   1473:            ha->cpar.write_back,ha->cpar.block_size));
                   1474: 
                   1475:     /* read board info, fill ctr_name[] */
                   1476:     if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_INFO,
                   1477:                          INVALID_CHANNEL,sizeof(gdth_binfo_str))) {
                   1478:        TRACE2(("BOARD_INFO supported!\n"));
                   1479:        strcpy(ha->ctr_name, ((gdth_binfo_str *)DMADATA(gdth_ctr_tab[hanum]))->type_string);
                   1480:     } else {
                   1481:        strcpy(ha->ctr_name, gdth_ctr_name(hanum));
                   1482:     }
                   1483:     TRACE2(("Controller name: %s\n",ha->ctr_name));
                   1484: 
                   1485:     /* initialize raw service */
                   1486:     if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0)) {
                   1487:         printk("GDT: Initialization error raw service (code %d)\n",
                   1488:                ha->status);
                   1489:         return 0;
                   1490:     }
                   1491:     TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n"));
                   1492: 
                   1493:     /* set/get features raw service (scatter/gather) */
                   1494:     ha->raw_feat = 0;
                   1495:     if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_SET_FEAT,SCATTER_GATHER,
                   1496:                           0,0)) {
                   1497:         TRACE2(("gdth_search_drives(): set features RAWSERVICE OK\n"));
                   1498:         if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_GET_FEAT,0,0,0)) {
                   1499:             TRACE2(("gdth_search_dr(): get feat RAWSERVICE %ld\n",
                   1500:                           ha->info));
                   1501:             ha->raw_feat = (ushort)ha->info;
                   1502:         }
                   1503:     } 
                   1504: 
                   1505:     /* set/get features cache service (equal to raw service) */
                   1506:     if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_SET_FEAT,0,
                   1507:                           SCATTER_GATHER,0)) {
                   1508:         TRACE2(("gdth_search_drives(): set features CACHESERVICE OK\n"));
                   1509:         if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_GET_FEAT,0,0,0)) {
                   1510:             TRACE2(("gdth_search_dr(): get feat CACHESERV. %ld\n",
                   1511:                           ha->info));
                   1512:             ha->cache_feat = (ushort)ha->info;
                   1513:         }
                   1514:     }
                   1515: 
                   1516:     /* reserve drives for raw service */
                   1517:     for (i = 0; reserve_list[i].hanum != 0xff; ++i) {
                   1518:        if (reserve_list[i].hanum < MAXHA && reserve_list[i].hanum == hanum &&
                   1519:            reserve_list[i].bus < MAXBUS && reserve_list[i].id < MAXID) {
                   1520:            TRACE2(("gdth_search_drives(): reserve ha %d bus %d id %d\n",
                   1521:                    reserve_list[i].hanum, reserve_list[i].bus,
                   1522:                    reserve_list[i].id));
                   1523:            if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE,0,
                   1524:                                   reserve_list[i].bus, reserve_list[i].id)) {
                   1525:                printk("GDT: Error raw service (RESERVE, code %d)\n",
                   1526:                       ha->status);
                   1527:            }
                   1528:        }
                   1529:     }
                   1530: 
                   1531:     /* scanning for raw devices */
                   1532:     for (b=0; b<ha->bus_cnt; ++b) {
                   1533:         for (t=0; t<MAXID; ++t) {
                   1534:             TRACE(("gdth_search_drives() rawd. bus %d id %d\n",b,t));
                   1535:             if (ha->id[b][t].type != SIOP_DTYP && 
                   1536:                 gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INFO,0,b,t)) {
                   1537:                 ha->id[b][t].type = RAW_DTYP;
                   1538:             }
                   1539:         }
                   1540:     }
                   1541: 
                   1542:     /* scanning for cache devices */
                   1543:     for (i=0; i<cdev_cnt && i<MAX_HDRIVES; ++i) {
                   1544:         TRACE(("gdth_search_drives() cachedev. %d\n",i));
                   1545:         if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_INFO,i,0,0)) {
                   1546:             /* dynamic relation between host drive number and Bus/ID */
                   1547:             /* search free position */
                   1548:             pos_found = FALSE;
                   1549:             for (b=0,t=0; b<ha->bus_cnt; ++b) {
                   1550:                 for (t=0; t<MAXID; ++t) {
                   1551:                     if (ha->id[b][t].type == EMPTY_DTYP) {
                   1552:                         pos_found = TRUE;
                   1553:                         break;
                   1554:                     }
                   1555:                 }
                   1556:                 if (pos_found)
                   1557:                     break;
                   1558:             }
                   1559:             TRACE(("gdth_search_dr() drive %d free pos at bus/id %d/%d\n",
                   1560:                          i,b,t));
                   1561: 
                   1562:             ha->id[b][t].type      = CACHE_DTYP;
                   1563:             ha->id[b][t].devtype   = 0;
                   1564:             ha->id[b][t].size      = ha->info;
                   1565:             ha->id[b][t].hostdrive = i;
                   1566: 
                   1567:             /* evaluate mapping (sectors per head, heads per cylinder) */
                   1568:            ha->id[b][t].size &= ~SECS32;
                   1569:            if (ha->info2 == 0) {
                   1570:                drv_cyls = ha->id[b][t].size /HEADS/SECS;
                   1571:                if (drv_cyls <= MAXCYLS) {
                   1572:                    drv_hds = HEADS;
                   1573:                    drv_secs= SECS;
                   1574:                } else {                            /* too high for 64*32 */
                   1575:                    drv_cyls = ha->id[b][t].size /MEDHEADS/MEDSECS;
                   1576:                    if (drv_cyls <= MAXCYLS) {
                   1577:                        drv_hds = MEDHEADS;
                   1578:                        drv_secs= MEDSECS;
                   1579:                    } else {                        /* too high for 127*63 */
                   1580:                        drv_cyls = ha->id[b][t].size /BIGHEADS/BIGSECS;
                   1581:                        drv_hds = BIGHEADS;
                   1582:                        drv_secs= BIGSECS;
                   1583:                    }
                   1584:                }
                   1585:             } else {
                   1586:                drv_hds = ha->info2 & 0xff;
                   1587:                drv_secs = (ha->info2 >> 8) & 0xff;
                   1588:                drv_cyls = ha->id[b][t].size /drv_hds/drv_secs;
                   1589:            }
                   1590:             ha->id[b][t].heads = (unchar)drv_hds;
                   1591:             ha->id[b][t].secs  = (unchar)drv_secs;
                   1592:             /* round size */
                   1593:             ha->id[b][t].size  = drv_cyls * drv_hds * drv_secs;
                   1594:             TRACE2(("gdth_search_dr() cdr. %d size %ld hds %ld scs %ld\n",
                   1595:                    i,ha->id[b][t].size,drv_hds,drv_secs));
                   1596:             
                   1597:             /* get informations about device */
                   1598:             if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_DEVTYPE,i,
                   1599:                                   0,0)) {
                   1600:                 TRACE(("gdth_search_dr() cache drive %d devtype %ld\n",
                   1601:                        i,ha->info));
                   1602:                 ha->id[b][t].devtype = (ushort)ha->info;
                   1603:             }
                   1604:         }
                   1605:     }
                   1606: 
                   1607:     TRACE(("gdth_search_drives() OK\n"));
                   1608:     return 1;
                   1609: }
                   1610: 
                   1611: 
                   1612: /* command queueing/sending functions */
                   1613: 
                   1614: static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority)
                   1615: {
                   1616:     register gdth_ha_str *ha;
                   1617:     register Scsi_Cmnd *pscp;
                   1618:     register Scsi_Cmnd *nscp;
                   1619:     ulong flags;
                   1620:     unchar b, t;
                   1621: 
                   1622:     TRACE(("gdth_putq() priority %d\n",priority));
                   1623:     save_flags(flags);
                   1624:     cli();
                   1625: 
                   1626:     ha = HADATA(gdth_ctr_tab[hanum]);
                   1627:     scp->SCp.this_residual = (int)priority;
                   1628:     gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6);
                   1629: #if LINUX_VERSION_CODE >= 0x020000
                   1630:     b = scp->channel;
                   1631: #else
                   1632:     b = NUMDATA(nscp->host)->busnum;
                   1633: #endif
                   1634:     t = scp->target;
                   1635: #if LINUX_VERSION_CODE >= 0x010300
                   1636:     if (priority >= DEFAULT_PRI && ha->id[b][t].lock) {
                   1637:         TRACE2(("gdth_putq(): locked IO -> update_timeout()\n"));
                   1638:         scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
                   1639:     }
                   1640: #endif
                   1641: 
                   1642:     if (ha->req_first==NULL) {
                   1643:         ha->req_first = scp;                    /* queue was empty */
                   1644:         scp->SCp.ptr = NULL;
                   1645:     } else {                                    /* queue not empty */
                   1646:         pscp = ha->req_first;
                   1647:         nscp = (Scsi_Cmnd *)pscp->SCp.ptr;
                   1648:         /* priority: 0-highest,..,0xff-lowest */
                   1649:         while (nscp && (unchar)nscp->SCp.this_residual <= priority) {
                   1650:             pscp = nscp;
                   1651:             nscp = (Scsi_Cmnd *)pscp->SCp.ptr;
                   1652:         }
                   1653:         pscp->SCp.ptr = (char *)scp;
                   1654:         scp->SCp.ptr  = (char *)nscp;
                   1655:     }
                   1656:     restore_flags(flags);
                   1657: 
                   1658: #ifdef GDTH_STATISTICS
                   1659:     flags = 0;
                   1660:     for (nscp=ha->req_first; nscp; nscp=(Scsi_Cmnd*)nscp->SCp.ptr)
                   1661:         ++flags;
                   1662:     if (max_rq < flags) {
                   1663:         max_rq = flags;
                   1664:         TRACE3(("GDT: max_rq = %d\n",(ushort)max_rq));
                   1665:     }
                   1666: #endif
                   1667: }
                   1668: 
                   1669: static void gdth_next(int hanum)
                   1670: {
                   1671:     register gdth_ha_str *ha;
                   1672:     register Scsi_Cmnd *pscp;
                   1673:     register Scsi_Cmnd *nscp;
                   1674:     unchar b, t, next_cmd, firsttime;
                   1675:     ushort hdrive;
                   1676:     ulong flags;
                   1677:     int cmd_index;
                   1678: 
                   1679:     TRACE(("gdth_next() hanum %d\n",hanum));
                   1680:     save_flags(flags);
                   1681:     cli();
                   1682: 
                   1683:     ha = HADATA(gdth_ctr_tab[hanum]);
                   1684:     ha->cmd_cnt = ha->cmd_offs_dpmem = 0;
                   1685:     next_cmd = firsttime = TRUE;
                   1686:     cmd_index = 0;
                   1687: 
                   1688:     for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) {
                   1689:         if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr)
                   1690:             pscp = (Scsi_Cmnd *)pscp->SCp.ptr;
                   1691: #if LINUX_VERSION_CODE >= 0x020000
                   1692:         b = nscp->channel;
                   1693: #else
                   1694:         b = NUMDATA(nscp->host)->busnum;
                   1695: #endif
                   1696:         t = nscp->target;
                   1697:         if (nscp->SCp.this_residual < DEFAULT_PRI || !ha->id[b][t].lock) {
                   1698: 
                   1699:             if (firsttime) {
                   1700:                 if (gdth_test_busy(hanum)) {        /* controller busy ? */
                   1701:                     TRACE(("gdth_next() controller %d busy !\n",hanum));
                   1702:                     if (!gdth_polling) {
                   1703:                         restore_flags(flags);
                   1704:                         return;
                   1705:                     }
                   1706:                     while (gdth_test_busy(hanum))
                   1707:                         gdth_delay(1);
                   1708:                 }
                   1709:                 firsttime = FALSE;
                   1710:             }
                   1711: 
                   1712: #if LINUX_VERSION_CODE >= 0x010300
                   1713:             if (nscp->done == gdth_scsi_done) {
                   1714:                 if (!(cmd_index=gdth_special_cmd(hanum,nscp,b)))
                   1715:                     next_cmd = FALSE;
                   1716:             } else
                   1717: #endif
                   1718:             if (ha->id[b][t].type != CACHE_DTYP) {
                   1719:                 if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,b)))
                   1720:                     next_cmd = FALSE;
                   1721:             } else {
                   1722:                 hdrive = ha->id[b][t].hostdrive;
                   1723:                 switch (nscp->cmnd[0]) {
                   1724:                   case TEST_UNIT_READY:
                   1725:                   case INQUIRY:
                   1726:                   case REQUEST_SENSE:
                   1727:                   case READ_CAPACITY:
                   1728:                   case VERIFY:
                   1729:                   case START_STOP:
                   1730:                   case MODE_SENSE:
                   1731:                     TRACE2(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
                   1732:                         nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
                   1733:                         nscp->cmnd[4],nscp->cmnd[5]));
                   1734:                         gdth_internal_cache_cmd(hanum,nscp,b,&flags);
                   1735:                     break;
                   1736: 
                   1737:                   case ALLOW_MEDIUM_REMOVAL:
                   1738:                     TRACE2(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
                   1739:                         nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
                   1740:                         nscp->cmnd[4],nscp->cmnd[5]));
                   1741:                     if ( (nscp->cmnd[4]&1) && !(ha->id[b][t].devtype&1) ) {
                   1742:                         TRACE2(("Prevent r. nonremov. drive->do nothing\n"));
                   1743:                         nscp->result = DID_OK << 16;
                   1744:                         restore_flags( flags );
                   1745:                         if (!nscp->SCp.have_data_in)
                   1746:                             nscp->SCp.have_data_in++;
                   1747:                         else
                   1748:                             nscp->scsi_done(nscp);
                   1749:                         save_flags( flags );
                   1750:                         cli();
                   1751:                     } else {
                   1752:                         nscp->cmnd[3] = (ha->id[b][t].devtype&1) ? 1:0;
                   1753:                         TRACE2(("Prevent/allow r. %d rem. drive %d\n",
                   1754:                             nscp->cmnd[4],nscp->cmnd[3]));
                   1755:                         if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,hdrive)))
                   1756:                             next_cmd = FALSE;
                   1757:                     }
                   1758:                     break;
                   1759: 
                   1760:                   case READ_6:
                   1761:                   case WRITE_6:
                   1762:                   case READ_10:
                   1763:                   case WRITE_10:
                   1764:                     if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,hdrive)))
                   1765:                         next_cmd = FALSE;
                   1766:                     break;
                   1767: 
                   1768:                   default:
                   1769:                     TRACE2(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
                   1770:                         nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
                   1771:                         nscp->cmnd[4],nscp->cmnd[5]));
                   1772:                     printk("GDT: Unknown SCSI command 0x%x to cache service !\n",
                   1773:                        nscp->cmnd[0]);
                   1774:                     nscp->result = DID_ABORT << 16;
                   1775:                     restore_flags( flags );
                   1776:                     if (!nscp->SCp.have_data_in)
                   1777:                         nscp->SCp.have_data_in++;
                   1778:                     else
                   1779:                         nscp->scsi_done(nscp);
                   1780:                     save_flags( flags );
                   1781:                     cli();
                   1782:                     break;
                   1783:                 }
                   1784:             }
                   1785: 
                   1786:             if (!next_cmd)
                   1787:                 break;
                   1788:             if (nscp == ha->req_first)
                   1789:                 ha->req_first = pscp = (Scsi_Cmnd *)nscp->SCp.ptr;
                   1790:             else
                   1791:                 pscp->SCp.ptr = nscp->SCp.ptr;
                   1792:             if (gdth_polling)
                   1793:                 break;
                   1794:         }
                   1795:     }
                   1796: 
                   1797:     if (ha->cmd_cnt > 0) {
                   1798:         gdth_release_event(hanum);
                   1799:     }
                   1800: 
                   1801:     restore_flags(flags);
                   1802: 
                   1803:     if (gdth_polling && ha->cmd_cnt > 0) {
                   1804:         if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT))
                   1805:             printk("GDT: Controller %d: Command %d timed out !\n",
                   1806:                    hanum,cmd_index);
                   1807:     }
                   1808: }
                   1809:     
                   1810: static void gdth_copy_internal_data(Scsi_Cmnd *scp,char *buffer,ushort count)
                   1811: {
                   1812:     ushort cpcount,i;
                   1813:     ushort cpsum,cpnow;
                   1814:     struct scatterlist *sl;
                   1815: 
                   1816:     cpcount = count<=(ushort)scp->bufflen ? count:(ushort)scp->bufflen;
                   1817:     if (scp->use_sg) {
                   1818:         sl = (struct scatterlist *)scp->request_buffer;
                   1819:         for (i=0,cpsum=0; i<scp->use_sg; ++i,++sl) {
                   1820:             cpnow = (ushort)sl->length;
                   1821:             TRACE(("copy_internal() now %d sum %d count %d %d\n",
                   1822:                           cpnow,cpsum,cpcount,(ushort)scp->bufflen));
                   1823:             if (cpsum+cpnow > cpcount) 
                   1824:                 cpnow = cpcount - cpsum;
                   1825:             cpsum += cpnow;
                   1826:             memcpy((char*)sl->address,buffer,cpnow);
                   1827:             if (cpsum == cpcount)
                   1828:                 break;
                   1829:             buffer += cpnow;
                   1830:         }
                   1831:     } else {
                   1832:         TRACE(("copy_internal() count %d\n",cpcount));
                   1833:         memcpy((char*)scp->request_buffer,buffer,cpcount);
                   1834:     }
                   1835: }
                   1836: 
                   1837: static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp,
                   1838:                                    unchar b,ulong *flags)
                   1839: {
                   1840:     register gdth_ha_str *ha;
                   1841:     ushort hdrive;
                   1842:     unchar t;
                   1843:     gdth_inq_data inq;
                   1844:     gdth_rdcap_data rdc;
                   1845:     gdth_sense_data sd;
                   1846:     gdth_modep_data mpd;
                   1847: 
                   1848:     ha = HADATA(gdth_ctr_tab[hanum]);
                   1849:     t  = scp->target;
                   1850:     hdrive = ha->id[b][t].hostdrive;
                   1851:     TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n",
                   1852:                  scp->cmnd[0],hdrive));
                   1853: 
                   1854:     if (scp->lun !=0)
                   1855:         scp->result = DID_BAD_TARGET << 16;
                   1856:     else {
                   1857:         switch (scp->cmnd[0]) {
                   1858:           case TEST_UNIT_READY:
                   1859:           case VERIFY:
                   1860:           case START_STOP:
                   1861:             TRACE2(("Test/Verify/Start hdrive %d\n",hdrive));
                   1862:             break;
                   1863: 
                   1864:           case INQUIRY:
                   1865:             TRACE2(("Inquiry hdrive %d devtype %d\n",
                   1866:                           hdrive,ha->id[b][t].devtype));
                   1867:             inq.type_qual = (ha->id[b][t].devtype&4) ? TYPE_ROM:TYPE_DISK;
                   1868:             /* you can here set all disks to removable, if you want to do
                   1869:                a flush using the ALLOW_MEDIUM_REMOVAL command */
                   1870:             inq.modif_rmb = ha->id[b][t].devtype&1 ? 0x80:0x00;
                   1871:             inq.version   = 2;
                   1872:             inq.resp_aenc = 2;
                   1873:             inq.add_length= 32;
                   1874:             strcpy(inq.vendor,"ICP    ");
                   1875:             sprintf(inq.product,"Host Drive  #%02d",hdrive);
                   1876:             strcpy(inq.revision,"   ");
                   1877:             gdth_copy_internal_data(scp,(char*)&inq,sizeof(gdth_inq_data));
                   1878:             break;
                   1879: 
                   1880:           case REQUEST_SENSE:
                   1881:             TRACE2(("Request sense hdrive %d\n",hdrive));
                   1882:             sd.errorcode = 0x70;
                   1883:             sd.segno     = 0x00;
                   1884:             sd.key       = NO_SENSE;
                   1885:             sd.info      = 0;
                   1886:             sd.add_length= 0;
                   1887:             gdth_copy_internal_data(scp,(char*)&sd,sizeof(gdth_sense_data));
                   1888:             break;
                   1889: 
                   1890:           case MODE_SENSE:
                   1891:             TRACE2(("Mode sense hdrive %d\n",hdrive));
                   1892:             memset((char*)&mpd,0,sizeof(gdth_modep_data));
                   1893:             mpd.hd.data_length = sizeof(gdth_modep_data);
                   1894:             mpd.hd.dev_par     = (ha->id[b][t].devtype&2) ? 0x80:0;
                   1895:             mpd.hd.bd_length   = sizeof(mpd.bd);
                   1896:             mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16;
                   1897:             mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8;
                   1898:             mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff);
                   1899:             gdth_copy_internal_data(scp,(char*)&mpd,sizeof(gdth_modep_data));
                   1900:             break;
                   1901: 
                   1902:           case READ_CAPACITY:
                   1903:             TRACE2(("Read capacity hdrive %d\n",hdrive));
                   1904:             rdc.last_block_no = ntohl(ha->id[b][t].size-1);
                   1905:             rdc.block_length  = ntohl(SECTOR_SIZE);
                   1906:             gdth_copy_internal_data(scp,(char*)&rdc,sizeof(gdth_rdcap_data));
                   1907:             break;
                   1908: 
                   1909:           default:
                   1910:             TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0]));
                   1911:             break;
                   1912:         }
                   1913:         scp->result = DID_OK << 16;
                   1914:     }
                   1915: 
                   1916:     restore_flags(*flags);
                   1917:     if (!scp->SCp.have_data_in)
                   1918:         scp->SCp.have_data_in++;
                   1919:     else
                   1920:         scp->scsi_done(scp);
                   1921:     save_flags(*flags);
                   1922:     cli();
                   1923:     return 1;
                   1924: }
                   1925:     
                   1926: static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
                   1927: {
                   1928:     register gdth_ha_str *ha;
                   1929:     register gdth_cmd_str *cmdp;
                   1930:     struct scatterlist *sl;
                   1931:     ushort i;
                   1932:     int cmd_index;
                   1933: 
                   1934:     ha = HADATA(gdth_ctr_tab[hanum]);
                   1935:     cmdp = ha->pccb;
                   1936:     TRACE(("gdth_fill_cache_cmd() cmd 0x%x cmdsize %d hdrive %d\n",
                   1937:                  scp->cmnd[0],scp->cmd_len,hdrive));
                   1938: 
                   1939:     if (ha->type==GDT_EISA && ha->cmd_cnt>0) 
                   1940:         return 0;
                   1941: 
                   1942:     cmdp->Service = CACHESERVICE;
                   1943:     cmdp->RequestBuffer = scp;
                   1944:     /* search free command index */
                   1945:     if (!(cmd_index=gdth_get_cmd_index(hanum))) {
                   1946:         TRACE(("GDT: No free command index found\n"));
                   1947:         return 0;
                   1948:     }
                   1949:     /* if it's the first command, set command semaphore */
                   1950:     if (ha->cmd_cnt == 0)
                   1951:         gdth_set_sema0(hanum);
                   1952: 
                   1953:     /* fill command */
                   1954:     if (scp->cmnd[0]==ALLOW_MEDIUM_REMOVAL) {
                   1955:         if (scp->cmnd[4] & 1)                   /* prevent ? */
                   1956:             cmdp->OpCode      = GDT_MOUNT;
                   1957:         else if (scp->cmnd[3] & 1)              /* removable drive ? */
                   1958:             cmdp->OpCode      = GDT_UNMOUNT;
                   1959:         else
                   1960:             cmdp->OpCode      = GDT_FLUSH;
                   1961:     } else {
                   1962:         if (scp->cmnd[0]==WRITE_6 || scp->cmnd[0]==WRITE_10) {
                   1963:             if (gdth_write_through)
                   1964:                 cmdp->OpCode  = GDT_WRITE_THR;
                   1965:             else
                   1966:                 cmdp->OpCode  = GDT_WRITE;
                   1967:         } else {
                   1968:             cmdp->OpCode      = GDT_READ;
                   1969:         }
                   1970:     }
                   1971: 
                   1972:     cmdp->BoardNode           = LOCALBOARD;
                   1973:     cmdp->u.cache.DeviceNo    = hdrive;
                   1974: 
                   1975:     if (scp->cmnd[0]==ALLOW_MEDIUM_REMOVAL) {
                   1976:         cmdp->u.cache.BlockNo = 1;
                   1977:         cmdp->u.cache.sg_canz = 0;
                   1978:     } else {
                   1979:         if (scp->cmd_len != 6) {
                   1980:             cmdp->u.cache.BlockNo = ntohl(*(ulong*)&scp->cmnd[2]);
                   1981:             cmdp->u.cache.BlockCnt= (ulong)ntohs(*(ushort*)&scp->cmnd[7]);
                   1982:         } else {
                   1983:             cmdp->u.cache.BlockNo = ntohl(*(ulong*)&scp->cmnd[0]) & 0x001fffffUL;
                   1984:             cmdp->u.cache.BlockCnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4];
                   1985:         }
                   1986: 
                   1987:         if (scp->use_sg) {
                   1988:             cmdp->u.cache.DestAddr= -1UL;
                   1989:             sl = (struct scatterlist *)scp->request_buffer;
                   1990:             for (i=0; i<scp->use_sg; ++i,++sl) {
                   1991:                 cmdp->u.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
                   1992:                 cmdp->u.cache.sg_lst[i].sg_len = (ulong)sl->length;
                   1993:             }
                   1994:             cmdp->u.cache.sg_canz = (ulong)i;
                   1995: 
                   1996: #ifdef GDTH_STATISTICS
                   1997:             if (max_sg < (ulong)i) {
                   1998:                 max_sg = (ulong)i;
                   1999:                 TRACE3(("GDT: max_sg = %d\n",i));
                   2000:             }
                   2001: #endif
                   2002:             if (i<GDTH_MAXSG)
                   2003:                 cmdp->u.cache.sg_lst[i].sg_len = 0;
                   2004:         } else {
                   2005:             if (ha->cache_feat & SCATTER_GATHER) {
                   2006:                 cmdp->u.cache.DestAddr = -1UL;
                   2007:                 cmdp->u.cache.sg_canz = 1;
                   2008:                 cmdp->u.cache.sg_lst[0].sg_ptr = virt_to_bus(scp->request_buffer);
                   2009:                 cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen;
                   2010:                 cmdp->u.cache.sg_lst[1].sg_len = 0;
                   2011:             } else {
                   2012:                 cmdp->u.cache.DestAddr  = virt_to_bus(scp->request_buffer);
                   2013:                 cmdp->u.cache.sg_canz= 0;
                   2014:             }
                   2015:         }
                   2016:     }
                   2017:     TRACE(("cache cmd: addr. %lx sganz %lx sgptr0 %lx sglen0 %lx\n",
                   2018:                   cmdp->u.cache.DestAddr,cmdp->u.cache.sg_canz,
                   2019:                   cmdp->u.cache.sg_lst[0].sg_ptr,
                   2020:                   cmdp->u.cache.sg_lst[0].sg_len));
                   2021:     TRACE(("cache cmd: cmd %d blockno. %ld, blockcnt %ld\n",
                   2022:                   cmdp->OpCode,cmdp->u.cache.BlockNo,cmdp->u.cache.BlockCnt));
                   2023: 
                   2024:     /* evaluate command size, check space */
                   2025:     ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) +
                   2026:         (ushort)cmdp->u.cache.sg_canz * sizeof(gdth_sg_str);
                   2027:     if (ha->cmd_len & 3)
                   2028:         ha->cmd_len += (4 - (ha->cmd_len & 3));
                   2029: 
                   2030:     if (ha->cmd_cnt > 0) {
                   2031:         if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
                   2032:             ha->ic_all_size) {
                   2033:             TRACE2(("gdth_fill_cache() DPMEM overflow\n"));
                   2034:             gdth_cmd_tab[cmd_index-2][hanum].cmnd = UNUSED_CMND;
                   2035:             return 0;
                   2036:         }
                   2037:     }
                   2038: 
                   2039:     /* copy command */
                   2040:     gdth_copy_command(hanum);
                   2041:     return cmd_index;
                   2042: }
                   2043: 
                   2044: static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
                   2045: {
                   2046:     register gdth_ha_str *ha;
                   2047:     register gdth_cmd_str *cmdp;
                   2048:     struct scatterlist *sl;
                   2049:     ushort i;
                   2050:     int cmd_index;
                   2051:     unchar t,l;
                   2052: 
                   2053:     ha = HADATA(gdth_ctr_tab[hanum]);
                   2054:     t = scp->target;
                   2055:     l = scp->lun;
                   2056:     cmdp = ha->pccb;
                   2057:     TRACE(("gdth_fill_raw_cmd() cmd 0x%x bus %d ID %d LUN %d\n",
                   2058:                  scp->cmnd[0],b,t,l));
                   2059: 
                   2060:     if (ha->type==GDT_EISA && ha->cmd_cnt>0) 
                   2061:         return 0;
                   2062: 
                   2063:     cmdp->Service = SCSIRAWSERVICE;
                   2064:     cmdp->RequestBuffer = scp;
                   2065:     /* search free command index */
                   2066:     if (!(cmd_index=gdth_get_cmd_index(hanum))) {
                   2067:         TRACE(("GDT: No free command index found\n"));
                   2068:         return 0;
                   2069:     }
                   2070:     /* if it's the first command, set command semaphore */
                   2071:     if (ha->cmd_cnt == 0)
                   2072:         gdth_set_sema0(hanum);
                   2073: 
                   2074:     /* fill command */  
                   2075:     cmdp->OpCode           = GDT_WRITE;         /* always */
                   2076:     cmdp->BoardNode        = LOCALBOARD;
                   2077:     cmdp->u.raw.reserved   = 0;
                   2078:     cmdp->u.raw.mdisc_time = 0;
                   2079:     cmdp->u.raw.mcon_time  = 0;
                   2080:     cmdp->u.raw.clen       = scp->cmd_len;
                   2081:     cmdp->u.raw.target     = t;
                   2082:     cmdp->u.raw.lun        = l;
                   2083:     cmdp->u.raw.bus        = b;
                   2084:     cmdp->u.raw.priority   = 0;
                   2085:     cmdp->u.raw.link_p     = NULL;
                   2086:     cmdp->u.raw.sdlen      = scp->request_bufflen;
                   2087:     cmdp->u.raw.sense_len  = 16;
                   2088:     cmdp->u.raw.sense_data = virt_to_bus(scp->sense_buffer);
                   2089:     cmdp->u.raw.direction  = 
                   2090:         gdth_direction_tab[scp->cmnd[0]]==DOU ? DATA_OUT : DATA_IN;
                   2091:     memcpy(cmdp->u.raw.cmd,scp->cmnd,12);
                   2092: 
                   2093:     if (scp->use_sg) {
                   2094:         cmdp->u.raw.sdata  = -1UL;
                   2095:         sl = (struct scatterlist *)scp->request_buffer;
                   2096:         for (i=0; i<scp->use_sg; ++i,++sl) {
                   2097:             cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
                   2098:             cmdp->u.raw.sg_lst[i].sg_len = (ulong)sl->length;
                   2099:         }
                   2100:         cmdp->u.raw.sg_ranz = (ulong)i;
                   2101: 
                   2102: #ifdef GDTH_STATISTICS
                   2103:         if (max_sg < (ulong)i) {
                   2104:             max_sg = (ulong)i;
                   2105:             TRACE3(("GDT: max_sg = %d\n",i));
                   2106:         }
                   2107: #endif
                   2108:         if (i<GDTH_MAXSG)
                   2109:             cmdp->u.raw.sg_lst[i].sg_len = 0;
                   2110:     } else {
                   2111:         if (ha->raw_feat & SCATTER_GATHER) {
                   2112:             cmdp->u.raw.sdata  = -1UL;
                   2113:             cmdp->u.raw.sg_ranz= 1;
                   2114:             cmdp->u.raw.sg_lst[0].sg_ptr = virt_to_bus(scp->request_buffer);
                   2115:             cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen;
                   2116:             cmdp->u.raw.sg_lst[1].sg_len = 0;
                   2117:         } else {
                   2118:             cmdp->u.raw.sdata  = virt_to_bus(scp->request_buffer);
                   2119:             cmdp->u.raw.sg_ranz= 0;
                   2120:         }
                   2121:     }
                   2122:     TRACE(("raw cmd: addr. %lx sganz %lx sgptr0 %lx sglen0 %lx\n",
                   2123:                   cmdp->u.raw.sdata,cmdp->u.raw.sg_ranz,
                   2124:                   cmdp->u.raw.sg_lst[0].sg_ptr,
                   2125:                   cmdp->u.raw.sg_lst[0].sg_len));
                   2126: 
                   2127:     /* evaluate command size, check space */
                   2128:     ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) +
                   2129:         (ushort)cmdp->u.raw.sg_ranz * sizeof(gdth_sg_str);
                   2130:     if (ha->cmd_len & 3)
                   2131:         ha->cmd_len += (4 - (ha->cmd_len & 3));
                   2132: 
                   2133:     if (ha->cmd_cnt > 0) {
                   2134:         if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
                   2135:             ha->ic_all_size) {
                   2136:             TRACE2(("gdth_fill_raw() DPMEM overflow\n"));
                   2137:             gdth_cmd_tab[cmd_index-2][hanum].cmnd = UNUSED_CMND;
                   2138:             return 0;
                   2139:         }
                   2140:     }
                   2141: 
                   2142:     /* copy command */
                   2143:     gdth_copy_command(hanum);
                   2144:     return cmd_index;
                   2145: }
                   2146: 
                   2147: static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
                   2148: {
                   2149:     register gdth_ha_str *ha;
                   2150:     register gdth_cmd_str *cmdp;
                   2151:     int cmd_index;
                   2152: 
                   2153:     ha  = HADATA(gdth_ctr_tab[hanum]);
                   2154:     cmdp= ha->pccb;
                   2155:     TRACE2(("gdth_special_cmd(): "));
                   2156: 
                   2157:     if (ha->type==GDT_EISA && ha->cmd_cnt>0) 
                   2158:         return 0;
                   2159: 
                   2160:     memcpy( cmdp, scp->request_buffer, sizeof(gdth_cmd_str));
                   2161:     cmdp->RequestBuffer = scp;
                   2162: 
                   2163:     /* search free command index */
                   2164:     if (!(cmd_index=gdth_get_cmd_index(hanum))) {
                   2165:         TRACE(("GDT: No free command index found\n"));
                   2166:         return 0;
                   2167:     }
                   2168: 
                   2169:     /* if it's the first command, set command semaphore */
                   2170:     if (ha->cmd_cnt == 0)
                   2171:        gdth_set_sema0(hanum);
                   2172: 
                   2173:     /* evaluate command size, check space */
                   2174:     if (cmdp->OpCode == GDT_IOCTL) {
                   2175:         TRACE2(("IOCTL\n"));
                   2176:         ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.ioctl.p_param) + sizeof(ulong);
                   2177:     } else if (cmdp->Service == CACHESERVICE) {
                   2178:         TRACE2(("cache command %d\n",cmdp->OpCode));
                   2179:         ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + sizeof(gdth_sg_str);
                   2180:     } else if (cmdp->Service == SCSIRAWSERVICE) {
                   2181:         TRACE2(("raw command %d/%d\n",cmdp->OpCode,cmdp->u.raw.cmd[0]));
                   2182:         ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + sizeof(gdth_sg_str);
                   2183:     }
                   2184: 
                   2185:     if (ha->cmd_len & 3)
                   2186:         ha->cmd_len += (4 - (ha->cmd_len & 3));
                   2187: 
                   2188:     if (ha->cmd_cnt > 0) {
                   2189:         if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
                   2190:             ha->ic_all_size) {
                   2191:             TRACE2(("gdth_special_cmd() DPMEM overflow\n"));
                   2192:             gdth_cmd_tab[cmd_index-2][hanum].cmnd = UNUSED_CMND;
                   2193:             return 0;
                   2194:         }
                   2195:     }
                   2196: 
                   2197:     /* copy command */
                   2198:     gdth_copy_command(hanum);
                   2199:     return cmd_index;
                   2200: }    
                   2201: 
                   2202: 
                   2203: /* Controller event handling functions */
                   2204: static gdth_evt_str *gdth_store_event(ushort source, ushort idx,
                   2205:                                       gdth_evt_data *evt)
                   2206: {
                   2207:     gdth_evt_str *e;
                   2208:     ulong flags;
                   2209:     struct timeval tv;
                   2210: 
                   2211:     TRACE2(("gdth_store_event() source %d idx %d\n", source, idx));
                   2212:     if (source == 0)                        /* no source -> no event */
                   2213:         return 0;
                   2214: 
                   2215:     save_flags(flags);
                   2216:     cli();
                   2217:     if (ebuffer[elastidx].event_source == source &&
                   2218:         ebuffer[elastidx].event_idx == idx &&
                   2219:         !memcmp((char *)&ebuffer[elastidx].event_data.eu,
                   2220:             (char *)&evt->eu, evt->size)) {
                   2221:         e = &ebuffer[elastidx];
                   2222:         do_gettimeofday(&tv);
                   2223:         e->last_stamp = tv.tv_sec;
                   2224:         ++e->same_count;
                   2225:     } else {
                   2226:         if (ebuffer[elastidx].event_source != 0) {  /* entry not free ? */
                   2227:             ++elastidx;
                   2228:             if (elastidx == MAX_EVENTS)
                   2229:                 elastidx = 0;
                   2230:             if (elastidx == eoldidx) {              /* reached mark ? */
                   2231:                 ++eoldidx;
                   2232:                 if (eoldidx == MAX_EVENTS)
                   2233:                     eoldidx = 0;
                   2234:             }
                   2235:         }
                   2236:         e = &ebuffer[elastidx];
                   2237:         e->event_source = source;
                   2238:         e->event_idx = idx;
                   2239:         do_gettimeofday(&tv);
                   2240:         e->first_stamp = e->last_stamp = tv.tv_sec;
                   2241:         e->same_count = 1;
                   2242:         e->event_data = *evt;
                   2243:     }
                   2244:     restore_flags(flags);
                   2245:     return e;
                   2246: }
                   2247: 
                   2248: static int gdth_read_event(int handle, gdth_evt_str *estr)
                   2249: {
                   2250:     gdth_evt_str *e;
                   2251:     int eindex;
                   2252:     ulong flags;
                   2253: 
                   2254:     TRACE2(("gdth_read_event() handle %d\n", handle));
                   2255:     save_flags(flags);
                   2256:     cli();
                   2257:     if (handle == -1)
                   2258:         eindex = eoldidx;
                   2259:     else
                   2260:         eindex = handle;
                   2261:     estr->event_source = 0;
                   2262: 
                   2263:     if (eindex >= MAX_EVENTS) {
                   2264:         restore_flags(flags);
                   2265:         return eindex;
                   2266:     }
                   2267:     e = &ebuffer[eindex];
                   2268:     if (e->event_source != 0) {
                   2269:         if (eindex != elastidx) {
                   2270:             if (++eindex == MAX_EVENTS)
                   2271:                 eindex = 0;
                   2272:         } else {
                   2273:             eindex = -1;
                   2274:         }
                   2275:         memcpy(estr, e, sizeof(gdth_evt_str));
                   2276:     }
                   2277:     restore_flags(flags);
                   2278:     return eindex;
                   2279: }
                   2280: 
                   2281: static void gdth_readapp_event(unchar application, gdth_evt_str *estr)
                   2282: {
                   2283:     gdth_evt_str *e;
                   2284:     int eindex;
                   2285:     ulong flags;
                   2286:     unchar found = FALSE;
                   2287: 
                   2288:     TRACE2(("gdth_readapp_event() app. %d\n", application));
                   2289:     save_flags(flags);
                   2290:     cli();
                   2291:     eindex = eoldidx;
                   2292:     for (;;) {
                   2293:         e = &ebuffer[eindex];
                   2294:         if (e->event_source == 0)
                   2295:             break;
                   2296:         if ((e->application & application) == 0) {
                   2297:             e->application |= application;
                   2298:             found = TRUE;
                   2299:             break;
                   2300:         }
                   2301:         if (eindex == elastidx)
                   2302:             break;
                   2303:         if (++eindex == MAX_EVENTS)
                   2304:             eindex = 0;
                   2305:     }
                   2306:     if (found)
                   2307:         memcpy(estr, e, sizeof(gdth_evt_str));
                   2308:     else
                   2309:         estr->event_source = 0;
                   2310:     restore_flags(flags);
                   2311: }
                   2312: 
                   2313: static void gdth_clear_events()
                   2314: {
                   2315:     ulong flags;
                   2316: 
                   2317:     TRACE(("gdth_clear_events()"));
                   2318:     save_flags(flags);
                   2319:     cli();
                   2320: 
                   2321:     eoldidx = elastidx = 0;
                   2322:     ebuffer[0].event_source = 0;
                   2323:     restore_flags(flags);
                   2324: }
                   2325: 
                   2326: 
                   2327: /* SCSI interface functions */
                   2328: 
                   2329: #if LINUX_VERSION_CODE >= 0x02015F
                   2330: static void do_gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
                   2331: {
                   2332:     ulong flags;
                   2333: 
                   2334:     spin_lock_irqsave(&io_request_lock, flags);
                   2335:     gdth_interrupt(irq, dev_id, regs);
                   2336:     spin_unlock_irqrestore(&io_request_lock, flags);
                   2337: }
                   2338: #endif
                   2339: 
                   2340: #if LINUX_VERSION_CODE >= 0x010346
                   2341: static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
                   2342: #else
                   2343: static void gdth_interrupt(int irq,struct pt_regs *regs)
                   2344: #endif
                   2345: {
                   2346:     register gdth_ha_str *ha;
                   2347:     gdt6m_dpram_str *dp6m_ptr;
                   2348:     gdt6_dpram_str *dp6_ptr;
                   2349:     gdt2_dpram_str *dp2_ptr;
                   2350:     Scsi_Cmnd *scp;
                   2351:     int hanum;
                   2352:     unchar IStatus;
                   2353:     ushort CmdStatus, Service = 0;
                   2354:     ulong InfoBytes, InfoBytes2 = 0;
                   2355:     gdth_evt_data dvr;
                   2356: 
                   2357:     TRACE(("gdth_interrupt() IRQ %d\n",irq));
                   2358: 
                   2359:     /* if polling and not from gdth_wait() -> return */
                   2360:     if (gdth_polling) {
                   2361:         if (!gdth_from_wait) {
                   2362:             return;
                   2363:         }
                   2364:     }
                   2365: 
                   2366:     wait_index = 0;
                   2367: 
                   2368:     /* search controller */
                   2369:     if ((hanum = gdth_get_status(&IStatus,irq)) == -1) {
                   2370:         /*
                   2371:         TRACE2(("gdth_interrupt(): Spurious interrupt received\n"));
                   2372:         */
                   2373:         return;
                   2374:     }
                   2375: 
                   2376: #ifdef GDTH_STATISTICS
                   2377:     ++act_ints;
                   2378: #endif
                   2379:     
                   2380:     ha = HADATA(gdth_ctr_tab[hanum]);
                   2381:     if (ha->type == GDT_EISA) {
                   2382:         if (IStatus & 0x80) {                   /* error flag */
                   2383:             IStatus &= ~0x80;
                   2384:             CmdStatus = inw(ha->bmic + MAILBOXREG+8);
                   2385:             TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
                   2386:             if (IStatus == ASYNCINDEX) {        /* async. event ? */
                   2387:                 Service = inw(ha->bmic + MAILBOXREG+10);
                   2388:                 InfoBytes2 = inl(ha->bmic + MAILBOXREG+4);
                   2389:             }
                   2390:         } else                                  /* no error */
                   2391:             CmdStatus = S_OK;
                   2392:         InfoBytes = inl(ha->bmic + MAILBOXREG+12);
                   2393:        if (gdth_polling)                       /* init. -> more info */
                   2394:            InfoBytes2 = inl(ha->bmic + MAILBOXREG+4);
                   2395:         outb(0xff, ha->bmic + EDOORREG);    /* acknowledge interrupt */
                   2396:         outb(0x00, ha->bmic + SEMA1REG);    /* reset status semaphore */
                   2397:     } else if (ha->type == GDT_ISA) {
                   2398:         dp2_ptr = (gdt2_dpram_str *)ha->brd;
                   2399:         if (IStatus & 0x80) {                   /* error flag */
                   2400:             IStatus &= ~0x80;
                   2401:             CmdStatus = readw(&dp2_ptr->u.ic.Status);
                   2402:             TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
                   2403:             if (IStatus == ASYNCINDEX) {        /* async. event ? */
                   2404:                 Service = readw(&dp2_ptr->u.ic.Service);
                   2405:                 InfoBytes2 = readl(&dp2_ptr->u.ic.Info[1]);
                   2406:             }
                   2407:         } else                                  /* no error */
                   2408:             CmdStatus = S_OK;
                   2409:         InfoBytes = readl(&dp2_ptr->u.ic.Info[0]);
                   2410:        if (gdth_polling)                       /* init. -> more info */
                   2411:            InfoBytes2 = readl(&dp2_ptr->u.ic.Info[1]);
                   2412:         writeb(0xff, &dp2_ptr->io.irqdel);              /* acknowledge interrupt */
                   2413:         writeb(0, &dp2_ptr->u.ic.Cmd_Index);            /* reset command index */
                   2414:         writeb(0, &dp2_ptr->io.Sema1);                 /* reset status semaphore */
                   2415:     } else if (ha->type == GDT_PCI) {
                   2416:         dp6_ptr = (gdt6_dpram_str *)ha->brd;
                   2417:         if (IStatus & 0x80) {                   /* error flag */
                   2418:             IStatus &= ~0x80;
                   2419:             CmdStatus = readw(&dp6_ptr->u.ic.Status);
                   2420:             TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
                   2421:             if (IStatus == ASYNCINDEX) {        /* async. event ? */
                   2422:                 Service = readw(&dp6_ptr->u.ic.Service);
                   2423:                 InfoBytes2 = readl(&dp6_ptr->u.ic.Info[1]);
                   2424:             }
                   2425:         } else                                  /* no error */
                   2426:             CmdStatus = S_OK;
                   2427:         InfoBytes = readl(&dp6_ptr->u.ic.Info[0]);
                   2428:        if (gdth_polling)                       /* init. -> more info */
                   2429:            InfoBytes2 = readl(&dp6_ptr->u.ic.Info[1]);
                   2430:         writeb(0xff, &dp6_ptr->io.irqdel);              /* acknowledge interrupt */
                   2431:         writeb(0, &dp6_ptr->u.ic.Cmd_Index);            /* reset command index */
                   2432:         writeb(0, &dp6_ptr->io.Sema1);                 /* reset status semaphore */
                   2433:     } else if (ha->type == GDT_PCINEW) {
                   2434:         if (IStatus & 0x80) {                   /* error flag */
                   2435:             IStatus &= ~0x80;
                   2436:             CmdStatus = inw(PTR2USHORT(&ha->plx->status));
                   2437:             TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
                   2438:             if (IStatus == ASYNCINDEX) {        /* async. event ? */
                   2439:                 Service = inw(PTR2USHORT(&ha->plx->service));
                   2440:                 InfoBytes2 = inl(PTR2USHORT(&ha->plx->info[1]));
                   2441:             }
                   2442:         } else
                   2443:             CmdStatus = S_OK;
                   2444: 
                   2445:         InfoBytes = inl(PTR2USHORT(&ha->plx->info[0]));
                   2446:        if (gdth_polling)                       /* init. -> more info */
                   2447:            InfoBytes2 = inl(PTR2USHORT(&ha->plx->info[1]));
                   2448:         outb(0xff, PTR2USHORT(&ha->plx->edoor_reg)); 
                   2449:         outb(0x00, PTR2USHORT(&ha->plx->sema1_reg)); 
                   2450:     } else if (ha->type == GDT_PCIMPR) {
                   2451:         dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
                   2452:         if (IStatus & 0x80) {                   /* error flag */
                   2453:             IStatus &= ~0x80;
                   2454:             CmdStatus = readw(&dp6m_ptr->i960r.status);
                   2455:             TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
                   2456:             if (IStatus == ASYNCINDEX) {        /* async. event ? */
                   2457:                 Service = readw(&dp6m_ptr->i960r.service);
                   2458:                 InfoBytes2 = readl(&dp6m_ptr->i960r.info[1]);
                   2459:             }
                   2460:         } else                                  /* no error */
                   2461:             CmdStatus = S_OK;
                   2462:         InfoBytes = readl(&dp6m_ptr->i960r.info[0]);
                   2463:        if (gdth_polling)                       /* init. -> more info */
                   2464:            InfoBytes2 = readl(&dp6m_ptr->i960r.info[1]);
                   2465:         writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
                   2466:         writeb(0, &dp6m_ptr->i960r.sema1_reg);
                   2467:     } else {
                   2468:         TRACE2(("gdth_interrupt() unknown controller type\n"));
                   2469:         return;
                   2470:     }
                   2471: 
                   2472:     TRACE(("gdth_interrupt() index %d stat %d info %ld\n",
                   2473:                  IStatus,CmdStatus,InfoBytes));
                   2474:     ha->status = CmdStatus;
                   2475:     ha->info   = InfoBytes;
                   2476:     ha->info2  = InfoBytes2;
                   2477: 
                   2478:     if (gdth_from_wait) {
                   2479:         wait_hanum = hanum;
                   2480:         wait_index = (int)IStatus;
                   2481:     }
                   2482: 
                   2483:     if (IStatus == ASYNCINDEX) {
                   2484:         TRACE2(("gdth_interrupt() async. event\n"));
                   2485:         gdth_async_event(hanum,Service);
                   2486:     } else {
                   2487:         if (IStatus == SPEZINDEX) {
                   2488:             TRACE2(("Service unknown or not initialized !\n"));
                   2489:             dvr.size = sizeof(dvr.eu.driver);
                   2490:             dvr.eu.driver.ionode = hanum;
                   2491:             gdth_store_event(ES_DRIVER, 4, &dvr);
                   2492:             return;
                   2493:         }
                   2494:         scp     = gdth_cmd_tab[IStatus-2][hanum].cmnd;
                   2495:         Service = gdth_cmd_tab[IStatus-2][hanum].service;
                   2496:         gdth_cmd_tab[IStatus-2][hanum].cmnd = UNUSED_CMND;
                   2497:         if (scp == UNUSED_CMND) {
                   2498:             TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus));
                   2499:             dvr.size = sizeof(dvr.eu.driver);
                   2500:             dvr.eu.driver.ionode = hanum;
                   2501:             dvr.eu.driver.index = IStatus;
                   2502:             gdth_store_event(ES_DRIVER, 1, &dvr);
                   2503:             return;
                   2504:         }
                   2505:         if (scp == INTERNAL_CMND) {
                   2506:             TRACE(("gdth_interrupt() answer to internal command\n"));
                   2507:             return;
                   2508:         }
                   2509:         TRACE(("gdth_interrupt() sync. status\n"));
                   2510:         gdth_sync_event(hanum,Service,IStatus,scp);
                   2511:     }
                   2512:     gdth_next(hanum);
                   2513: }
                   2514: 
                   2515: static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
                   2516: {
                   2517:     register gdth_ha_str *ha;
                   2518:     gdth_msg_str *msg;
                   2519:     gdth_cmd_str *cmdp;
                   2520:     char c='\r';
                   2521:     ushort i;
                   2522:     gdth_evt_data dvr;
                   2523: 
                   2524:     ha   = HADATA(gdth_ctr_tab[hanum]);
                   2525:     cmdp = ha->pccb;
                   2526:     TRACE(("gdth_sync_event() scp %lx serv %d status %d\n",
                   2527:                  (ulong)scp,service,ha->status));
                   2528: 
                   2529:     if (service == SCREENSERVICE) {
                   2530:         msg  = (gdth_msg_str *)ha->pscratch;
                   2531:         TRACE(("len: %ld, answer: %d, ext: %d, alen: %ld\n",
                   2532:                      msg->msg_len,msg->msg_answer,msg->msg_ext,msg->msg_alen));
                   2533:         if (msg->msg_len)
                   2534:             if (!(msg->msg_answer && msg->msg_ext)) {
                   2535:                 msg->msg_text[msg->msg_len] = '\0';
                   2536:                 printk("%s",msg->msg_text);
                   2537:             }
                   2538: 
                   2539:         if (msg->msg_ext && !msg->msg_answer) {
                   2540:             while (gdth_test_busy(hanum))
                   2541:                 gdth_delay(0);
                   2542:             cmdp->Service       = SCREENSERVICE;
                   2543:             cmdp->RequestBuffer = SCREEN_CMND;
                   2544:             gdth_get_cmd_index(hanum);
                   2545:             gdth_set_sema0(hanum);
                   2546:             cmdp->OpCode        = GDT_READ;
                   2547:             cmdp->BoardNode     = LOCALBOARD;
                   2548:             cmdp->u.screen.reserved  = 0;
                   2549:             cmdp->u.screen.msg_handle= msg->msg_handle;
                   2550:             cmdp->u.screen.msg_addr  = (ulong)msg;
                   2551:             ha->cmd_offs_dpmem = 0;
                   2552:             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.msg_addr) 
                   2553:                 + sizeof(ulong);
                   2554:             ha->cmd_cnt = 0;
                   2555:             gdth_copy_command(hanum);
                   2556:             gdth_release_event(hanum);
                   2557:             return 1;
                   2558:         }
                   2559: 
                   2560:         if (msg->msg_answer && msg->msg_alen) {
                   2561:             for (i=0; i<msg->msg_alen && i<MSGLEN; ++i) {
                   2562:                 /* getchar() ?? */           
                   2563:                 /* .. */
                   2564:                 if (c == '\r')
                   2565:                     break;
                   2566:                 msg->msg_text[i] = c; 
                   2567:             }
                   2568:             msg->msg_alen -= i;
                   2569:             if (c!='\r' && msg->msg_alen!=0) {
                   2570:                 msg->msg_answer = 1;
                   2571:                 msg->msg_ext    = 1;
                   2572:             } else {
                   2573:                 msg->msg_ext    = 0;
                   2574:                 msg->msg_answer = 0;
                   2575:             }
                   2576:             msg->msg_len = i;
                   2577:             while (gdth_test_busy(hanum))
                   2578:                 gdth_delay(0);
                   2579:             cmdp->Service       = SCREENSERVICE;
                   2580:             cmdp->RequestBuffer = SCREEN_CMND;
                   2581:             gdth_get_cmd_index(hanum);
                   2582:             gdth_set_sema0(hanum);
                   2583:             cmdp->OpCode        = GDT_WRITE;
                   2584:             cmdp->BoardNode     = LOCALBOARD;
                   2585:             cmdp->u.screen.reserved  = 0;
                   2586:             cmdp->u.screen.msg_handle= msg->msg_handle;
                   2587:             cmdp->u.screen.msg_addr  = (ulong)msg;
                   2588:             ha->cmd_offs_dpmem = 0;
                   2589:             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.msg_addr) 
                   2590:                 + sizeof(ulong);
                   2591:             ha->cmd_cnt = 0;
                   2592:             gdth_copy_command(hanum);
                   2593:             gdth_release_event(hanum);
                   2594:             return 1;
                   2595:         }
                   2596:         printk("\n");
                   2597: 
                   2598:     } else {
                   2599:         scp->SCp.Message = (int)ha->status;
                   2600:         /* cache or raw service */
                   2601:         if (ha->status == S_OK) {
                   2602:             scp->result = DID_OK << 16;
                   2603:         } else if (ha->status == S_BSY) {
                   2604:             TRACE2(("Controller busy -> retry !\n"));
                   2605:             gdth_putq(hanum,scp,scp->SCp.this_residual);
                   2606:             return 1;
                   2607:         } else {
                   2608:             if (service == CACHESERVICE) {
                   2609:                 memset((char*)scp->sense_buffer,0,16);
                   2610:                 scp->sense_buffer[0] = 0x70;
                   2611:                 scp->sense_buffer[2] = NOT_READY;
                   2612:                 scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
                   2613: 
                   2614:                 if (scp->done != gdth_scsi_done) {
                   2615:                     dvr.size = sizeof(dvr.eu.sync);
                   2616:                     dvr.eu.sync.ionode  = hanum;
                   2617:                     dvr.eu.sync.service = service;
                   2618:                     dvr.eu.sync.status  = ha->status;
                   2619:                     dvr.eu.sync.info    = ha->info;
                   2620:                     dvr.eu.sync.hostdrive =
                   2621: #if LINUX_VERSION_CODE >= 0x020000
                   2622:                         ha->id[scp->channel][scp->target].hostdrive;
                   2623: #else
                   2624:                         ha->id[NUMDATA(scp->host)->busnum][scp->target].hostdrive;
                   2625: #endif
                   2626:                     if (ha->status >= 0x8000)
                   2627:                         gdth_store_event(ES_SYNC, 0, &dvr);
                   2628:                     else
                   2629:                         gdth_store_event(ES_SYNC, service, &dvr);
                   2630:                 }
                   2631:             } else {
                   2632:                 if (ha->status!=S_RAW_SCSI || ha->status==S_RAW_ILL || ha->info>=0x100) {
                   2633:                     scp->result = DID_BAD_TARGET << 16;
                   2634:                 } else {
                   2635:                     scp->result = (DID_OK << 16) | ha->info;
                   2636:                 }
                   2637:             }
                   2638:         }
                   2639:        if (!scp->SCp.have_data_in)
                   2640:            scp->SCp.have_data_in++;
                   2641:        else
                   2642:            scp->scsi_done(scp);
                   2643:     }
                   2644: 
                   2645:     return 1;
                   2646: }
                   2647: 
                   2648: static char *async_cache_tab[] = {
                   2649: /* 0*/  "\011\000\002\002\002\004\002\006\004"
                   2650:         "GDT HA %u, service %u, async. status %u/%lu unknown",
                   2651: /* 1*/  "\011\000\002\002\002\004\002\006\004"
                   2652:         "GDT HA %u, service %u, async. status %u/%lu unknown",
                   2653: /* 2*/  "\005\000\002\006\004"
                   2654:         "GDT HA %u, Host Drive %lu not ready",
                   2655: /* 3*/  "\005\000\002\006\004"
                   2656:         "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",
                   2657: /* 4*/  "\005\000\002\006\004"
                   2658:         "GDT HA %u, mirror update on Host Drive %lu failed",
                   2659: /* 5*/  "\005\000\002\006\004"
                   2660:         "GDT HA %u, Mirror Drive %lu failed",
                   2661: /* 6*/  "\005\000\002\006\004"
                   2662:         "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",
                   2663: /* 7*/  "\005\000\002\006\004"
                   2664:         "GDT HA %u, Host Drive %lu write protected",
                   2665: /* 8*/  "\005\000\002\006\004"
                   2666:         "GDT HA %u, media changed in Host Drive %lu",
                   2667: /* 9*/  "\005\000\002\006\004"
                   2668:         "GDT HA %u, Host Drive %lu is offline",
                   2669: /*10*/  "\005\000\002\006\004"
                   2670:         "GDT HA %u, media change of Mirror Drive %lu",
                   2671: /*11*/  "\005\000\002\006\004"
                   2672:         "GDT HA %u, Mirror Drive %lu is write protected",
                   2673: /*12*/  "\005\000\002\006\004"
                   2674:         "GDT HA %u, general error on Host Drive %lu. Please check the devices of this drive!",
                   2675: /*13*/  "\007\000\002\006\002\010\002"
                   2676:         "GDT HA %u, Array Drive %u: Cache Drive %u failed",
                   2677: /*14*/  "\005\000\002\006\002"
                   2678:         "GDT HA %u, Array Drive %u: FAIL state entered",
                   2679: /*15*/  "\005\000\002\006\002"
                   2680:         "GDT HA %u, Array Drive %u: error",
                   2681: /*16*/  "\007\000\002\006\002\010\002"
                   2682:         "GDT HA %u, Array Drive %u: failed drive replaced by Cache Drive %u",
                   2683: /*17*/  "\005\000\002\006\002"
                   2684:         "GDT HA %u, Array Drive %u: parity build failed",
                   2685: /*18*/  "\005\000\002\006\002"
                   2686:         "GDT HA %u, Array Drive %u: drive rebuild failed",
                   2687: /*19*/  "\007\000\002\010\002"
                   2688:         "GDT HA %u, Test of Hot Fix %u failed",
                   2689: /*20*/  "\005\000\002\006\002"
                   2690:         "GDT HA %u, Array Drive %u: drive build finished successfully",
                   2691: /*21*/  "\005\000\002\006\002"
                   2692:         "GDT HA %u, Array Drive %u: drive rebuild finished successfully",
                   2693: /*22*/  "\007\000\002\006\002\010\002"
                   2694:         "GDT HA %u, Array Drive %u: Hot Fix %u activated",
                   2695: /*23*/  "\005\000\002\006\002"
                   2696:         "GDT HA %u, Host Drive %u: processing of i/o aborted due to serious drive error",
                   2697: /*24*/  "\005\000\002\010\002"
                   2698:         "GDT HA %u, mirror update on Cache Drive %u completed",
                   2699: /*25*/  "\005\000\002\010\002"
                   2700:         "GDT HA %u, mirror update on Cache Drive %lu failed",
                   2701: /*26*/  "\005\000\002\006\002"
                   2702:         "GDT HA %u, Array Drive %u: drive rebuild started",
                   2703: /*27*/  "\005\000\002\012\001"
                   2704:         "GDT HA %u, Fault bus %u: SHELF OK detected",
                   2705: /*28*/  "\005\000\002\012\001"
                   2706:         "GDT HA %u, Fault bus %u: SHELF not OK detected",
                   2707: /*29*/  "\007\000\002\012\001\013\001"
                   2708:         "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug started",
                   2709: /*30*/  "\007\000\002\012\001\013\001"
                   2710:         "GDT HA %u, Fault bus %u, ID %u: new disk detected",
                   2711: /*31*/  "\007\000\002\012\001\013\001"
                   2712:         "GDT HA %u, Fault bus %u, ID %u: old disk detected",
                   2713: /*32*/  "\007\000\002\012\001\013\001"
                   2714:         "GDT HA %u, Fault bus %u, ID %u: plugging an active disk is illegal",
                   2715: /*33*/  "\007\000\002\012\001\013\001"
                   2716:         "GDT HA %u, Fault bus %u, ID %u: illegal device detected",
                   2717: /*34*/  "\011\000\002\012\001\013\001\006\004"
                   2718:         "GDT HA %u, Fault bus %u, ID %u: insufficient disk capacity (%lu MB required)",
                   2719: /*35*/  "\007\000\002\012\001\013\001"
                   2720:         "GDT HA %u, Fault bus %u, ID %u: disk write protected",
                   2721: /*36*/  "\007\000\002\012\001\013\001"
                   2722:         "GDT HA %u, Fault bus %u, ID %u: disk not available",
                   2723: /*37*/  "\007\000\002\012\001\006\004"
                   2724:         "GDT HA %u, Fault bus %u: swap detected (%lu)",
                   2725: /*38*/  "\007\000\002\012\001\013\001"
                   2726:         "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug finished successfully",
                   2727: /*39*/  "\007\000\002\012\001\013\001"
                   2728:         "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug aborted due to user Hot Plug",
                   2729: /*40*/  "\007\000\002\012\001\013\001"
                   2730:         "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug aborted",
                   2731: /*41*/  "\007\000\002\012\001\013\001"
                   2732:         "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug for Hot Fix started",
                   2733: /*42*/  "\005\000\002\006\002"
                   2734:         "GDT HA %u, Array Drive %u: drive build started",
                   2735: /*43*/  "\003\000\002"
                   2736:         "GDT HA %u, DRAM parity error detected",
                   2737: /*44*/  "\005\000\002\006\002"
                   2738:         "GDT HA %u, Mirror Drive %u: update started",
                   2739: /*45*/  "\007\000\002\006\002\010\002"
                   2740:         "GDT HA %u, Mirror Drive %u: Hot Fix %u activated",
                   2741: /*46*/  "\005\000\002\006\002"
                   2742:         "GDT HA %u, Array Drive %u: no matching Pool Hot Fix Drive available",
                   2743: /*47*/  "\005\000\002\006\002"
                   2744:         "GDT HA %u, Array Drive %u: Pool Hot Fix Drive available",
                   2745: /*48*/  "\005\000\002\006\002"
                   2746:         "GDT HA %u, Mirror Drive %u: no matching Pool Hot Fix Drive available",
                   2747: /*49*/  "\005\000\002\006\002"
                   2748:         "GDT HA %u, Mirror Drive %u: Pool Hot Fix Drive available",
                   2749: /*50*/  "\007\000\002\012\001\013\001"
                   2750:         "GDT HA %u, SCSI bus %u, ID %u: IGNORE_WIDE_RESIDUE message received",
                   2751: /*51*/  "\005\000\002\006\002"
                   2752:         "GDT HA %u, Array Drive %u: expand started",
                   2753: /*52*/  "\005\000\002\006\002"
                   2754:         "GDT HA %u, Array Drive %u: expand finished successfully",
                   2755: /*53*/  "\005\000\002\006\002"
                   2756:         "GDT HA %u, Array Drive %u: expand failed",
                   2757: /*54*/  "\003\000\002"
                   2758:         "GDT HA %u, CPU temperature critical",
                   2759: /*55*/  "\003\000\002"
                   2760:         "GDT HA %u, CPU temperature OK",
                   2761: /*56*/  "\005\000\002\006\004"
                   2762:         "GDT HA %u, Host drive %lu created",
                   2763: /*57*/  "\005\000\002\006\002"
                   2764:         "GDT HA %u, Array Drive %u: expand restarted",
                   2765: /*58*/  "\005\000\002\006\002"
                   2766:         "GDT HA %u, Array Drive %u: expand stopped",
                   2767: };
                   2768: 
                   2769: 
                   2770: static int gdth_async_event(int hanum,int service)
                   2771: {
                   2772:     gdth_stackframe stack;
                   2773:     gdth_evt_data dvr;
                   2774:     char *f = NULL;
                   2775:     int i,j;
                   2776:     gdth_ha_str *ha;
                   2777:     gdth_msg_str *msg;
                   2778:     gdth_cmd_str *cmdp;
                   2779:     int cmd_index;
                   2780: 
                   2781:     ha  = HADATA(gdth_ctr_tab[hanum]);
                   2782:     cmdp= ha->pccb;
                   2783:     msg = (gdth_msg_str *)ha->pscratch;
                   2784:     TRACE2(("gdth_async_event() ha %d serv %d\n",
                   2785:                  hanum,service));
                   2786: 
                   2787:     if (service == SCREENSERVICE) {
                   2788:         if (ha->status == MSG_REQUEST) {
                   2789:             while (gdth_test_busy(hanum))
                   2790:                 gdth_delay(0);
                   2791:             cmdp->Service       = SCREENSERVICE;
                   2792:             cmdp->RequestBuffer = SCREEN_CMND;
                   2793:             cmd_index = gdth_get_cmd_index(hanum);
                   2794:             gdth_set_sema0(hanum);
                   2795:             cmdp->OpCode        = GDT_READ;
                   2796:             cmdp->BoardNode     = LOCALBOARD;
                   2797:             cmdp->u.screen.reserved  = 0;
                   2798:             cmdp->u.screen.msg_handle= MSG_INV_HANDLE;
                   2799:             cmdp->u.screen.msg_addr  = (ulong)msg;
                   2800:             ha->cmd_offs_dpmem = 0;
                   2801:             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.msg_addr) 
                   2802:                 + sizeof(ulong);
                   2803:             ha->cmd_cnt = 0;
                   2804:             gdth_copy_command(hanum);
                   2805:             if (ha->type == GDT_EISA)
                   2806:                 printk("[EISA slot %d] ",(ushort)ha->brd_phys);
                   2807:             else if (ha->type == GDT_ISA)
                   2808:                 printk("[DPMEM 0x%4X] ",(ushort)ha->brd_phys);
                   2809:             else 
                   2810:                 printk("[PCI %d/%d] ",(ushort)(ha->brd_phys>>8),
                   2811:                        (ushort)((ha->brd_phys>>3)&0x1f));
                   2812:             gdth_release_event(hanum);
                   2813:         }
                   2814: 
                   2815:     } else {
                   2816:         dvr.size = sizeof(dvr.eu.async);
                   2817:         dvr.eu.async.ionode   = hanum;
                   2818:         dvr.eu.async.service = service;
                   2819:         dvr.eu.async.status  = ha->status;
                   2820:         dvr.eu.async.info    = ha->info;
                   2821:         *(ulong *)dvr.eu.async.scsi_coord  = ha->info2;
                   2822:         gdth_store_event(ES_ASYNC, service, &dvr);
                   2823: 
                   2824:         if (service==CACHESERVICE && INDEX_OK(ha->status,async_cache_tab)) {
                   2825:             TRACE2(("GDT: Async. event cache service, event no.: %d\n",
                   2826:                 ha->status));
                   2827:         
                   2828:             f = async_cache_tab[ha->status];
                   2829: 
                   2830:             /* i: parameter to push, j: stack element to fill */
                   2831:             for (j=0,i=1; i < f[0]; i+=2) {
                   2832:                 switch (f[i+1]) {
                   2833:                   case 4:
                   2834:                     stack.b[j++] = *(ulong*)&dvr.eu.stream[(int)f[i]];
                   2835:                     break;
                   2836:                   case 2:
                   2837:                     stack.b[j++] = *(ushort*)&dvr.eu.stream[(int)f[i]];
                   2838:                     break;
                   2839:                   case 1:
                   2840:                     stack.b[j++] = *(unchar*)&dvr.eu.stream[(int)f[i]];
                   2841:                     break;
                   2842:                   default:
                   2843:                     break;
                   2844:                 }
                   2845:             }
                   2846: 
                   2847:             printk(&f[f[0]],stack); printk("\n");
                   2848: 
                   2849:         } else {
                   2850:             printk("GDT: Unknown async. event service %d event no. %d\n",
                   2851:                 service,ha->status);
                   2852:         }
                   2853:     }
                   2854:     return 1;
                   2855: }
                   2856: 
                   2857: 
                   2858: #ifdef GDTH_STATISTICS
                   2859: void gdth_timeout(ulong data)
                   2860: {
                   2861:     ulong flags,i;
                   2862:     Scsi_Cmnd *nscp;
                   2863:     gdth_ha_str *ha;
                   2864:     int hanum = 0;
                   2865: 
                   2866:     save_flags(flags);
                   2867:     cli();
                   2868: 
                   2869:     for (act_stats=0,i=0; i<GDTH_MAXCMDS; ++i) 
                   2870:         if (gdth_cmd_tab[i][hanum].cmnd != UNUSED_CMND)
                   2871:             ++act_stats;
                   2872: 
                   2873:     ha = HADATA(gdth_ctr_tab[hanum]);
                   2874:     for (act_rq=0,nscp=ha->req_first; nscp; nscp=(Scsi_Cmnd*)nscp->SCp.ptr)
                   2875:         ++act_rq;
                   2876: 
                   2877:     TRACE2(("gdth_to(): ints %ld, ios %ld, act_stats %ld, act_rq %ld\n",
                   2878:             act_ints, act_ios, act_stats, act_rq));
                   2879:     act_ints = act_ios = 0;
                   2880: 
                   2881:     gdth_timer.expires = jiffies + 30 * HZ;
                   2882:     add_timer(&gdth_timer);
                   2883:     restore_flags(flags);
                   2884: }
                   2885: #endif
                   2886: 
                   2887: 
                   2888: __initfunc (int gdth_detect(Scsi_Host_Template *shtp))
                   2889: {
                   2890:     struct Scsi_Host *shp;
                   2891:     gdth_ha_str *ha;
                   2892:     unsigned long flags;
                   2893:     ulong isa_bios;
                   2894:     ushort eisa_slot,device_id,index;
                   2895:     gdth_pci_str pcistr;
                   2896:     int i,j,hanum;
                   2897:     unchar b;
                   2898:     
                   2899:  
                   2900: #ifdef DEBUG_GDTH
                   2901:     printk("GDT: This driver contains debugging information !! Trace level = %d\n",
                   2902:         DebugState);
                   2903:     printk("     Destination of debugging information: ");
                   2904: #ifdef __SERIAL__
                   2905: #ifdef __COM2__
                   2906:     printk("Serial port COM2\n");
                   2907: #else
                   2908:     printk("Serial port COM1\n");
                   2909: #endif
                   2910: #else
                   2911:     printk("Console\n");
                   2912: #endif
                   2913:     gdth_delay(3000);
                   2914: #endif
                   2915: 
                   2916:     TRACE(("gdth_detect()\n"));
                   2917: 
                   2918:     if (disable_gdth_scan) {
                   2919:         printk("GDT: Controller driver disabled from command line !\n");
                   2920:         return 0;
                   2921:     }
                   2922: 
                   2923:     /* initializations */
                   2924:     gdth_polling = TRUE; b = 0;
                   2925:     for (i=0; i<GDTH_MAXCMDS; ++i)
                   2926:         for (j=0; j<MAXHA; ++j)
                   2927:             gdth_cmd_tab[i][j].cmnd = UNUSED_CMND;
                   2928:     for (i=0; i<4; ++i)
                   2929:         for (j=0; j<MAXHA; ++j)
                   2930:             gdth_ioctl_tab[i][j] = NULL;
                   2931:     gdth_clear_events();
                   2932: 
                   2933:     /* scanning for controllers, at first: ISA controller */
                   2934:     for (isa_bios=0xc8000UL; isa_bios<=0xd8000UL; isa_bios+=0x8000UL) {
                   2935:         if (gdth_search_isa(isa_bios)) {        /* controller found */
                   2936:             shp = scsi_register(shtp,sizeof(gdth_ext_str));
                   2937:             ha = HADATA(shp);
                   2938:             if (!gdth_init_isa(isa_bios,ha)) {
                   2939:                 scsi_unregister(shp);
                   2940:                 continue;
                   2941:             }
                   2942:             /* controller found and initialized */
                   2943:             printk("Configuring GDT-ISA HA at BIOS 0x%05lX IRQ %u DRQ %u\n",
                   2944:                    isa_bios,ha->irq,ha->drq);
                   2945: 
                   2946:             save_flags(flags);
                   2947:             cli();
                   2948: #if LINUX_VERSION_CODE >= 0x02015F 
                   2949:             if (request_irq(ha->irq,do_gdth_interrupt,SA_INTERRUPT,"gdth",NULL))
                   2950: #elif LINUX_VERSION_CODE >= 0x010346 
                   2951:             if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",NULL))
                   2952: #else
                   2953:             if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) 
                   2954: #endif
                   2955:             {
                   2956:                 printk("GDT-ISA: Unable to allocate IRQ\n");
                   2957:                 restore_flags(flags);
                   2958:                 scsi_unregister(shp);
                   2959:                 continue;
                   2960:             }
                   2961:             if (request_dma(ha->drq,"gdth")) {
                   2962:                 printk("GDT-ISA: Unable to allocate DMA channel\n");
                   2963: #if LINUX_VERSION_CODE >= 0x010346 
                   2964:                 free_irq(ha->irq,NULL);
                   2965: #else
                   2966:                 free_irq(ha->irq);
                   2967: #endif
                   2968:                 restore_flags(flags);
                   2969:                 scsi_unregister(shp);
                   2970:                 continue;
                   2971:             }
                   2972:             set_dma_mode(ha->drq,DMA_MODE_CASCADE);
                   2973:             enable_dma(ha->drq);
                   2974:             shp->unchecked_isa_dma = 1;
                   2975:             shp->irq = ha->irq;
                   2976:             shp->dma_channel = ha->drq;
                   2977:             for (i=0; i<MAXID; ++i) {
                   2978:                 if (ha->id[0][i].type==SIOP_DTYP) {
                   2979:                     shp->this_id = i;
                   2980:                     break;
                   2981:                 }
                   2982:             }
                   2983:             hanum = gdth_ctr_count;         
                   2984:             gdth_ctr_tab[gdth_ctr_count++] = shp;
                   2985:             gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
                   2986: 
                   2987:             NUMDATA(shp)->hanum = (ushort)hanum;
                   2988:             NUMDATA(shp)->busnum= 0;
                   2989: 
                   2990:             ha->pccb = CMDDATA(shp);
                   2991:             ha->pscratch = DMADATA(shp);
                   2992:             ha->req_first = NULL;
                   2993:             for (i=0; i<MAXBUS; ++i) {
                   2994:                 for (j=0; j<MAXID; ++j) {
                   2995:                     ha->id[i][j].type = EMPTY_DTYP;
                   2996:                     ha->id[i][j].lock = 0;
                   2997:                    ha->id[i][j].heads = 0;
                   2998:                 }
                   2999:             }
                   3000:             restore_flags(flags);
                   3001: 
                   3002:             if (!gdth_search_drives(hanum)) {
                   3003:                 printk("GDT-ISA: Error during device scan\n");
                   3004:                 --gdth_ctr_count;
                   3005:                --gdth_ctr_vcount;
                   3006:                 save_flags(flags);
                   3007:                 cli();
                   3008: #if LINUX_VERSION_CODE >= 0x010346 
                   3009:                 free_irq(ha->irq,NULL);
                   3010: #else
                   3011:                 free_irq(ha->irq);
                   3012: #endif
                   3013:                 restore_flags(flags);
                   3014:                 scsi_unregister(shp);
                   3015:                 continue;
                   3016:             }
                   3017: 
                   3018: #if LINUX_VERSION_CODE >= 0x020000
                   3019:             shp->max_id      = 8;
                   3020:             shp->max_lun     = MAXLUN;
                   3021:             shp->max_channel = ha->bus_cnt - 1;
                   3022: #else
                   3023:             /* register addit. SCSI channels as virtual controllers */
                   3024:             for (b=1; b<ha->bus_cnt; ++b) {
                   3025:                 shp = scsi_register(shtp,sizeof(gdth_num_str));
                   3026:                 shp->unchecked_isa_dma = 1;
                   3027:                 shp->irq = ha->irq;
                   3028:                 shp->dma_channel = ha->drq;
                   3029:                 for (i=0; i<MAXID; ++i) {
                   3030:                     if (ha->id[b][i].type==SIOP_DTYP) {
                   3031:                         shp->this_id = i;
                   3032:                         break;
                   3033:                     }
                   3034:                 }
                   3035:                 gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
                   3036:                 NUMDATA(shp)->hanum = (ushort)hanum;
                   3037:                 NUMDATA(shp)->busnum = b;
                   3038:             }
                   3039: #endif
                   3040: 
                   3041:             gdth_enable_int(hanum);
                   3042:         }
                   3043:     }
                   3044: 
                   3045:     /* scanning for EISA controllers */
                   3046:     for (eisa_slot=0x1000; eisa_slot<=0x8000; eisa_slot+=0x1000) {
                   3047:         if (gdth_search_eisa(eisa_slot)) {      /* controller found */
                   3048:             shp = scsi_register(shtp,sizeof(gdth_ext_str));
                   3049:             ha = HADATA(shp);
                   3050:             if (!gdth_init_eisa(eisa_slot,ha)) {
                   3051:                 scsi_unregister(shp);
                   3052:                 continue;
                   3053:             }
                   3054:             /* controller found and initialized */
                   3055:             printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n",
                   3056:                    eisa_slot>>12,ha->irq);
                   3057: 
                   3058:             save_flags(flags);
                   3059:             cli();
                   3060: #if LINUX_VERSION_CODE >= 0x02015F 
                   3061:             if (request_irq(ha->irq,do_gdth_interrupt,SA_INTERRUPT,"gdth",NULL))
                   3062: #elif LINUX_VERSION_CODE >= 0x010346 
                   3063:             if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",NULL))
                   3064: #else
                   3065:             if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) 
                   3066: #endif
                   3067:             {
                   3068:                 printk("GDT-EISA: Unable to allocate IRQ\n");
                   3069:                 restore_flags(flags);
                   3070:                 scsi_unregister(shp);
                   3071:                 continue;
                   3072:             }
                   3073:             shp->unchecked_isa_dma = 0;
                   3074:             shp->irq = ha->irq;
                   3075:             shp->dma_channel = 0xff;
                   3076:             for (i=0; i<MAXID; ++i) {
                   3077:                 if (ha->id[0][i].type==SIOP_DTYP) {
                   3078:                     shp->this_id = i;
                   3079:                     break;
                   3080:                 }
                   3081:             }
                   3082:             hanum = gdth_ctr_count;
                   3083:             gdth_ctr_tab[gdth_ctr_count++] = shp;
                   3084:             gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
                   3085: 
                   3086:             NUMDATA(shp)->hanum = (ushort)hanum;
                   3087:             NUMDATA(shp)->busnum= 0;
                   3088:             TRACE2(("EISA detect Bus 0: shp %lx hanum %d\n",
                   3089:                           (ulong)shp,NUMDATA(shp)->hanum));
                   3090: 
                   3091:             ha->pccb = CMDDATA(shp);
                   3092:             ha->pscratch = DMADATA(shp);
                   3093:             ha->req_first = NULL;
                   3094:             for (i=0; i<MAXBUS; ++i) {
                   3095:                 for (j=0; j<MAXID; ++j) {
                   3096:                     ha->id[i][j].type = EMPTY_DTYP;
                   3097:                     ha->id[i][j].lock = 0;
                   3098:                    ha->id[i][j].heads = 0;
                   3099:                 }
                   3100:             }
                   3101:             restore_flags(flags);
                   3102: 
                   3103:             if (!gdth_search_drives(hanum)) {
                   3104:                 printk("GDT-EISA: Error during device scan\n");
                   3105:                 --gdth_ctr_count;
                   3106:                --gdth_ctr_vcount;
                   3107:                 save_flags(flags);
                   3108:                 cli();
                   3109: #if LINUX_VERSION_CODE >= 0x010346 
                   3110:                 free_irq(ha->irq,NULL);
                   3111: #else
                   3112:                 free_irq(ha->irq);
                   3113: #endif
                   3114:                 restore_flags(flags);
                   3115:                 scsi_unregister(shp);
                   3116:                 continue;
                   3117:             }
                   3118: 
                   3119: #if LINUX_VERSION_CODE >= 0x020000
                   3120:             shp->max_id      = 8;
                   3121:             shp->max_lun     = MAXLUN;
                   3122:             shp->max_channel = ha->bus_cnt - 1;
                   3123: #else
                   3124:             /* register addit. SCSI channels as virtual controllers */
                   3125:             for (b=1; b<ha->bus_cnt; ++b) {
                   3126:                 shp = scsi_register(shtp,sizeof(gdth_num_str));
                   3127:                 shp->unchecked_isa_dma = 0;
                   3128:                 shp->irq = ha->irq;
                   3129:                 shp->dma_channel = 0xff;
                   3130:                 for (i=0; i<MAXID; ++i) {
                   3131:                     if (ha->id[b][i].type==SIOP_DTYP) {
                   3132:                         shp->this_id = i;
                   3133:                         break;
                   3134:                     }
                   3135:                 }
                   3136:                 gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
                   3137:                 NUMDATA(shp)->hanum = (ushort)hanum;
                   3138:                 NUMDATA(shp)->busnum = b;
                   3139:                 TRACE2(("EISA detect Bus %d: shp %lx hanum %d\n",
                   3140:                               NUMDATA(shp)->busnum,(ulong)shp,
                   3141:                               NUMDATA(shp)->hanum));
                   3142:             }
                   3143: #endif
                   3144: 
                   3145:             gdth_enable_int(hanum);
                   3146:         }
                   3147:     }
                   3148: 
                   3149:     /* scanning for PCI controllers */
                   3150:     for (device_id = 0; device_id <= PCI_DEVICE_ID_VORTEX_GDTMAXRP; ++device_id) {
                   3151:         if (device_id > PCI_DEVICE_ID_VORTEX_GDT6555 &&
                   3152:             device_id < PCI_DEVICE_ID_VORTEX_GDT6x17RP)
                   3153:             continue;
                   3154:         for (index = 0; ; ++index) {
                   3155:             if (!gdth_search_pci(device_id,index,&pcistr)) 
                   3156:                 break;                          /* next device_id */
                   3157:             shp = scsi_register(shtp,sizeof(gdth_ext_str));
                   3158:             ha = HADATA(shp);
                   3159:             if (!gdth_init_pci(&pcistr,ha)) {
                   3160:                 scsi_unregister(shp);
                   3161:                 continue;
                   3162:             }
                   3163:             /* controller found and initialized */
                   3164:             printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n",
                   3165:                    pcistr.bus,pcistr.device_fn>>3,ha->irq);
                   3166: 
                   3167:             save_flags(flags);
                   3168:             cli();
                   3169: #if LINUX_VERSION_CODE >= 0x02015F 
                   3170:             if (request_irq(ha->irq,do_gdth_interrupt,SA_INTERRUPT|SA_SHIRQ,"gdth",NULL))
                   3171: #elif LINUX_VERSION_CODE >= 0x010346 
                   3172:             if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT|SA_SHIRQ,"gdth",NULL))
                   3173: #else
                   3174:             if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT|SA_SHIRQ,"gdth")) 
                   3175: #endif
                   3176:             {
                   3177:                 printk("GDT-PCI: Unable to allocate IRQ\n");
                   3178:                 restore_flags(flags);
                   3179:                 scsi_unregister(shp);
                   3180:                 continue;
                   3181:             }
                   3182:             shp->unchecked_isa_dma = 0;
                   3183:             shp->irq = ha->irq;
                   3184:             shp->dma_channel = 0xff;
                   3185:             for (i=0; i<MAXID; ++i) {
                   3186:                 if (ha->id[0][i].type==SIOP_DTYP) {
                   3187:                     shp->this_id = i;
                   3188:                     break;
                   3189:                 }
                   3190:             }
                   3191:             hanum = gdth_ctr_count;
                   3192:             gdth_ctr_tab[gdth_ctr_count++] = shp;
                   3193:             gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
                   3194: 
                   3195:             NUMDATA(shp)->hanum = (ushort)hanum;
                   3196:             NUMDATA(shp)->busnum= 0;
                   3197: 
                   3198:             ha->pccb = CMDDATA(shp);
                   3199:             ha->pscratch = DMADATA(shp);
                   3200:             ha->req_first = NULL;
                   3201:             for (i=0; i<MAXBUS; ++i) {
                   3202:                 for (j=0; j<MAXID; ++j) {
                   3203:                     ha->id[i][j].type = EMPTY_DTYP;
                   3204:                     ha->id[i][j].lock = 0;
                   3205:                    ha->id[i][j].heads = 0;
                   3206:                 }
                   3207:             }
                   3208:             restore_flags(flags);
                   3209: 
                   3210:             if (!gdth_search_drives(hanum)) {
                   3211:                 printk("GDT-PCI: Error during device scan\n");
                   3212:                 --gdth_ctr_count;
                   3213:                --gdth_ctr_vcount;
                   3214:                 save_flags(flags);
                   3215:                 cli();
                   3216: #if LINUX_VERSION_CODE >= 0x010346 
                   3217:                 free_irq(ha->irq,NULL);
                   3218: #else
                   3219:                 free_irq(ha->irq);
                   3220: #endif
                   3221:                 restore_flags(flags);
                   3222:                 scsi_unregister(shp);
                   3223:                 continue;
                   3224:             }
                   3225: 
                   3226: #if LINUX_VERSION_CODE >= 0x020000
                   3227:             shp->max_id      = MAXID;
                   3228:             shp->max_lun     = MAXLUN;
                   3229:             shp->max_channel = ha->bus_cnt - 1;
                   3230: #else
                   3231:             /* register addit. SCSI channels as virtual controllers */
                   3232:             for (b=1; b<ha->bus_cnt; ++b) {
                   3233:                 shp = scsi_register(shtp,sizeof(gdth_num_str));
                   3234:                 shp->unchecked_isa_dma = 0;
                   3235:                 shp->irq = ha->irq;
                   3236:                 shp->dma_channel = 0xff;
                   3237:                 for (i=0; i<MAXID; ++i) {
                   3238:                     if (ha->id[b][i].type==SIOP_DTYP) {
                   3239:                         shp->this_id = i;
                   3240:                         break;
                   3241:                     }
                   3242:                 }
                   3243:                 gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
                   3244:                 NUMDATA(shp)->hanum = (ushort)hanum;
                   3245:                 NUMDATA(shp)->busnum = b;
                   3246:             }
                   3247: #endif
                   3248: 
                   3249:             gdth_enable_int(hanum);
                   3250:         }
                   3251:     }
                   3252: 
                   3253:     TRACE2(("gdth_detect() %d controller detected\n",gdth_ctr_count));
                   3254:     if (gdth_ctr_count > 0) {
                   3255: #ifdef GDTH_STATISTICS
                   3256:        TRACE2(("gdth_detect(): Initializing timer !\n"));
                   3257:        init_timer(&gdth_timer);
                   3258:        gdth_timer.expires = jiffies + HZ;
                   3259:        gdth_timer.data = 0L;
                   3260:        gdth_timer.function = gdth_timeout;
                   3261:        add_timer(&gdth_timer);
                   3262: #endif
                   3263: #if LINUX_VERSION_CODE >= 0x020100
                   3264:        register_reboot_notifier(&gdth_notifier);
                   3265: #endif
                   3266:     }
                   3267:     gdth_polling = FALSE;
                   3268:     return gdth_ctr_vcount;
                   3269: }
                   3270: 
                   3271: 
                   3272: int gdth_release(struct Scsi_Host *shp)
                   3273: {
                   3274:     unsigned long flags;
                   3275: 
                   3276:     TRACE2(("gdth_release()\n"));
                   3277: 
                   3278:     if (NUMDATA(shp)->busnum == 0) {
                   3279:        gdth_flush(NUMDATA(shp)->hanum);
                   3280: 
                   3281:        save_flags(flags);
                   3282:        cli();
                   3283:         if (shp->irq) {
                   3284: #if LINUX_VERSION_CODE >= 0x010346
                   3285:             free_irq(shp->irq,NULL);
                   3286: #else
                   3287:             free_irq(shp->irq);
                   3288: #endif
                   3289:         }
                   3290:         if (shp->dma_channel != 0xff) {
                   3291:             free_dma(shp->dma_channel);
                   3292:         }
                   3293:        restore_flags(flags);
                   3294:        gdth_ctr_released++;
                   3295:        TRACE2(("gdth_release(): HA %d of %d\n", 
                   3296:                gdth_ctr_released, gdth_ctr_count));
                   3297: 
                   3298:        if (gdth_ctr_released == gdth_ctr_count) {
                   3299: #ifdef GDTH_STATISTICS
                   3300:            del_timer(&gdth_timer);
                   3301: #endif
                   3302: #if LINUX_VERSION_CODE >= 0x020100
                   3303:            unregister_reboot_notifier(&gdth_notifier);
                   3304: #endif
                   3305:        }
                   3306:     }
                   3307: 
                   3308:     scsi_unregister(shp);
                   3309:     return 0;
                   3310: }
                   3311:             
                   3312: 
                   3313: static const char *gdth_ctr_name(int hanum)
                   3314: {
                   3315:     gdth_ha_str *ha;
                   3316: 
                   3317:     TRACE2(("gdth_ctr_name()\n"));
                   3318: 
                   3319:     ha    = HADATA(gdth_ctr_tab[hanum]);
                   3320: 
                   3321:     if (ha->type == GDT_EISA) {
                   3322:         switch (ha->stype) {
                   3323:           case GDT3_ID:
                   3324:             return("GDT3000/3020");
                   3325:           case GDT3A_ID:
                   3326:             return("GDT3000A/3020A/3050A");
                   3327:           case GDT3B_ID:
                   3328:             return("GDT3000B/3010A");
                   3329:         }
                   3330:     } else if (ha->type == GDT_ISA) {
                   3331:         return("GDT2000/2020");
                   3332:     } else if (ha->type == GDT_PCI) {
                   3333:         switch (ha->stype) {
                   3334:           case PCI_DEVICE_ID_VORTEX_GDT60x0:
                   3335:             return("GDT6000/6020/6050");
                   3336:           case PCI_DEVICE_ID_VORTEX_GDT6000B:
                   3337:             return("GDT6000B/6010");
                   3338:         }
                   3339:     } 
                   3340:     /* new controllers (GDT_PCINEW, GDT_PCIMPR, ..) use board_info IOCTL! */
                   3341: 
                   3342:     return("");
                   3343: }
                   3344: 
                   3345: const char *gdth_info(struct Scsi_Host *shp)
                   3346: {
                   3347:     int hanum;
                   3348:     gdth_ha_str *ha;
                   3349: 
                   3350:     TRACE2(("gdth_info()\n"));
                   3351:     hanum = NUMDATA(shp)->hanum;
                   3352:     ha    = HADATA(gdth_ctr_tab[hanum]);
                   3353: 
                   3354:     return ((const char *)ha->ctr_name);
                   3355: }
                   3356: 
                   3357: /* old error handling */
                   3358: int gdth_abort(Scsi_Cmnd *scp)
                   3359: {
                   3360:     TRACE2(("gdth_abort() reason %d\n",scp->abort_reason));
                   3361:     return SCSI_ABORT_SNOOZE;
                   3362: }
                   3363: 
                   3364: #if LINUX_VERSION_CODE >= 0x010346
                   3365: int gdth_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
                   3366: #else
                   3367: int gdth_reset(Scsi_Cmnd *scp)
                   3368: #endif
                   3369: {
                   3370:     TRACE2(("gdth_reset()\n"));
                   3371:     return SCSI_RESET_PUNT;
                   3372: }
                   3373: 
                   3374: #if LINUX_VERSION_CODE >= 0x02015F
                   3375: /* new error handling */
                   3376: int gdth_eh_abort(Scsi_Cmnd *scp)
                   3377: {
                   3378:     TRACE2(("gdth_eh_abort()\n"));
                   3379:     return FAILED;
                   3380: }
                   3381: 
                   3382: int gdth_eh_device_reset(Scsi_Cmnd *scp)
                   3383: {
                   3384:     TRACE2(("gdth_eh_device_reset()\n"));
                   3385:     return FAILED;
                   3386: }
                   3387: 
                   3388: int gdth_eh_bus_reset(Scsi_Cmnd *scp)
                   3389: {
                   3390:     TRACE2(("gdth_eh_bus_reset()\n"));
                   3391:     return FAILED;
                   3392: }
                   3393: 
                   3394: int gdth_eh_host_reset(Scsi_Cmnd *scp)
                   3395: {
                   3396:     TRACE2(("gdth_eh_host_reset()\n"));
                   3397:     return FAILED;
                   3398: }
                   3399: #endif
                   3400: 
                   3401: #if LINUX_VERSION_CODE >= 0x010300
                   3402: int gdth_bios_param(Disk *disk,kdev_t dev,int *ip)
                   3403: #else
                   3404: int gdth_bios_param(Disk *disk,int dev,int *ip)
                   3405: #endif
                   3406: {
                   3407:     unchar b, t;
                   3408:     int hanum;
                   3409:     gdth_ha_str *ha;
                   3410:     int drv_hds, drv_secs;
                   3411: 
                   3412:     hanum = NUMDATA(disk->device->host)->hanum;
                   3413:     b = disk->device->channel;
                   3414:     t = disk->device->id;
                   3415:     TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", hanum, b, t));
                   3416:     ha = HADATA(gdth_ctr_tab[hanum]);
                   3417: 
                   3418:     if (ha->id[b][t].heads == 0) {
                   3419:        /* raw device: evaluate mapping (sectors per head, heads per cylinder) */
                   3420:        if (disk->capacity /HEADS/SECS <= MAXCYLS) {
                   3421:            drv_hds = HEADS;
                   3422:            drv_secs= SECS;
                   3423:        } else if (disk->capacity /MEDHEADS/MEDSECS <= MAXCYLS) {
                   3424:            drv_hds = MEDHEADS;
                   3425:            drv_secs= MEDSECS;
                   3426:        } else {
                   3427:            drv_hds = BIGHEADS;
                   3428:            drv_secs= BIGSECS;
                   3429:        }
                   3430:        ha->id[b][t].heads = drv_hds;
                   3431:        ha->id[b][t].secs = drv_secs;
                   3432:        TRACE2(("gdth_bios_param(): raw device -> params evaluated\n"));
                   3433:     }
                   3434: 
                   3435:     ip[0] = ha->id[b][t].heads;
                   3436:     ip[1] = ha->id[b][t].secs;
                   3437:     ip[2] = disk->capacity / ip[0] / ip[1];
                   3438: 
                   3439:     TRACE2(("gdth_bios_param(): %d heads, %d secs, %d cyls\n",
                   3440:             ip[0],ip[1],ip[2]));
                   3441:     return 0;
                   3442: }
                   3443: 
                   3444: 
                   3445: static void internal_done(Scsi_Cmnd *scp)
                   3446: {
                   3447:     scp->SCp.sent_command++;
                   3448: }
                   3449: 
                   3450: int gdth_command(Scsi_Cmnd *scp)
                   3451: {
                   3452:     TRACE2(("gdth_command()\n"));
                   3453: 
                   3454:     scp->SCp.sent_command = 0;
                   3455:     gdth_queuecommand(scp,internal_done);
                   3456: 
                   3457:     while (!scp->SCp.sent_command)
                   3458:         barrier();
                   3459:     return scp->result;
                   3460: }
                   3461: 
                   3462: 
                   3463: int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *))
                   3464: {
                   3465:     int hanum;
                   3466:     int priority;
                   3467: 
                   3468:     TRACE(("gdth_queuecommand() cmd 0x%x id %d lun %d\n",
                   3469:                   scp->cmnd[0],scp->target,scp->lun));
                   3470:     
                   3471:     scp->scsi_done = (void *)done;
                   3472:     scp->SCp.have_data_in = 1;
                   3473:     hanum = NUMDATA(scp->host)->hanum;
                   3474: #ifdef GDTH_STATISTICS
                   3475:     ++act_ios;
                   3476: #endif
                   3477: 
                   3478:     priority = DEFAULT_PRI;
                   3479: #if LINUX_VERSION_CODE >= 0x010300
                   3480:     if (scp->done == gdth_scsi_done)
                   3481:         priority = scp->SCp.this_residual;
                   3482: #endif
                   3483:     gdth_putq( hanum, scp, priority );
                   3484:     gdth_next( hanum );
                   3485:     return 0;
                   3486: }
                   3487: 
                   3488: /* flush routine */
                   3489: static void gdth_flush(int hanum)
                   3490: {
                   3491:     int             i, j;
                   3492:     gdth_ha_str     *ha;
                   3493:     Scsi_Cmnd       scp;
                   3494:     Scsi_Device     sdev;
                   3495:     gdth_cmd_str    gdtcmd;
                   3496:     char            cmnd[12];
                   3497: 
                   3498:     TRACE2(("gdth_flush() hanum %d\n",hanum));
                   3499:     ha = HADATA(gdth_ctr_tab[hanum]);
                   3500:     memset(&sdev,0,sizeof(Scsi_Device));
                   3501:     memset(&scp, 0,sizeof(Scsi_Cmnd));
                   3502:     sdev.host = gdth_ctr_tab[hanum];
                   3503:     sdev.id = sdev.host->this_id;
                   3504:     scp.cmd_len = 12;
                   3505:     scp.host = gdth_ctr_tab[hanum];
                   3506:     scp.target = sdev.host->this_id;
                   3507:     scp.device = &sdev;
                   3508:     scp.use_sg = 0;
                   3509: 
                   3510:     for (i = 0; i < MAXBUS; ++i) {
                   3511:        for (j = 0; j < MAXID; ++j) {
                   3512:            if (ha->id[i][j].type == CACHE_DTYP) {
                   3513:                gdtcmd.BoardNode = LOCALBOARD;
                   3514:                gdtcmd.Service = CACHESERVICE;
                   3515:                gdtcmd.OpCode = GDT_FLUSH;
                   3516:                gdtcmd.u.cache.DeviceNo = ha->id[i][j].hostdrive;
                   3517:                gdtcmd.u.cache.BlockNo = 1;
                   3518:                gdtcmd.u.cache.sg_canz = 0;
                   3519:                TRACE2(("gdth_flush(): flush ha %d drive %d\n",
                   3520:                         hanum, ha->id[i][j].hostdrive));
                   3521:                {
                   3522:                    struct semaphore sem = MUTEX_LOCKED;
                   3523:                    scp.request.rq_status = RQ_SCSI_BUSY;
                   3524:                    scp.request.sem = &sem;
                   3525:                    scp.SCp.this_residual = IOCTL_PRI;
                   3526:                    scsi_do_cmd(&scp, cmnd, &gdtcmd,
                   3527:                                sizeof(gdth_cmd_str), gdth_scsi_done,
                   3528:                                30*HZ, 1);
                   3529:                    down(&sem);
                   3530:                }
                   3531:            }
                   3532:        }
                   3533:     }
                   3534: }
                   3535: 
                   3536: /* shutdown routine */
                   3537: #if LINUX_VERSION_CODE >= 0x020100
                   3538: static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
                   3539: #else
                   3540: void gdth_halt(void)
                   3541: #endif
                   3542: {
                   3543:     int             hanum;
                   3544:     Scsi_Cmnd       scp;
                   3545:     Scsi_Device     sdev;
                   3546:     gdth_cmd_str    gdtcmd;
                   3547:     char            cmnd[12];
                   3548: 
                   3549: #if LINUX_VERSION_CODE >= 0x020100
                   3550:     TRACE2(("gdth_halt() event %d\n",event));
                   3551:     if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
                   3552:        return NOTIFY_DONE;
                   3553: #else
                   3554:     TRACE2(("gdth_halt()\n"));
                   3555:     if (halt_called) {
                   3556:        TRACE2(("already called\n"));
                   3557:        return;
                   3558:     }
                   3559:     halt_called = TRUE;
                   3560: #endif
                   3561:     printk("GDT: Flushing all host drives .. ");
                   3562:     for (hanum = 0; hanum < gdth_ctr_count; ++hanum) {
                   3563:         gdth_flush(hanum);
                   3564: 
                   3565:         /* controller reset */
                   3566:         memset(&sdev,0,sizeof(Scsi_Device));
                   3567:         memset(&scp, 0,sizeof(Scsi_Cmnd));
                   3568:         sdev.host = gdth_ctr_tab[hanum];
                   3569:         sdev.id = sdev.host->this_id;
                   3570:         scp.cmd_len = 12;
                   3571:         scp.host = gdth_ctr_tab[hanum];
                   3572:         scp.target = sdev.host->this_id;
                   3573:         scp.device = &sdev;
                   3574:         scp.use_sg = 0;
                   3575: 
                   3576:         gdtcmd.BoardNode = LOCALBOARD;
                   3577:         gdtcmd.Service = CACHESERVICE;
                   3578:         gdtcmd.OpCode = GDT_RESET;
                   3579:         TRACE2(("gdth_halt(): reset controller %d\n", hanum));
                   3580:         {
                   3581:             struct semaphore sem = MUTEX_LOCKED;
                   3582:             scp.request.rq_status = RQ_SCSI_BUSY;
                   3583:             scp.request.sem = &sem;
                   3584:             scp.SCp.this_residual = IOCTL_PRI;
                   3585:             scsi_do_cmd(&scp, cmnd, &gdtcmd,
                   3586:                 sizeof(gdth_cmd_str), gdth_scsi_done,
                   3587:                 10*HZ, 1);
                   3588:             down(&sem);
                   3589:         }
                   3590:     }
                   3591:     printk("Done.\n");
                   3592: 
                   3593: #ifdef GDTH_STATISTICS
                   3594:     del_timer(&gdth_timer);
                   3595: #endif
                   3596: #if LINUX_VERSION_CODE >= 0x020100
                   3597:     unregister_reboot_notifier(&gdth_notifier);
                   3598:     return NOTIFY_OK;
                   3599: #endif
                   3600: }
                   3601: 
                   3602: 
                   3603: /* called from init/main.c */
                   3604: __initfunc (void gdth_setup(char *str,int *ints))
                   3605: {
                   3606:     static size_t setup_idx = 0;
                   3607: 
                   3608:     TRACE2(("gdth_setup() str %s ints[0] %d ints[1] %d\n",
                   3609:                   str ? str:"NULL", ints[0],
                   3610:                   ints[0] ? ints[1]:0));
                   3611: 
                   3612:     if (setup_idx >= MAXHA) {
                   3613:         printk("GDT: gdth_setup() called too many times. Bad LILO params ?\n");
                   3614:         return;
                   3615:     }
                   3616:     if (ints[0] != 1) {
                   3617:         printk("GDT: Illegal command line !\n");
                   3618:         printk("Usage: gdth=<IRQ>\n");
                   3619:         printk("Where: <IRQ>: valid EISA controller IRQ (10,11,12,14)\n");
                   3620:         printk("              or 0 to disable controller driver\n");
                   3621:         return;
                   3622:     }
                   3623:     if (ints[1] == 10 || ints[1] == 11 || ints[1] == 12 || ints[1] == 14) {
                   3624:         irqs[setup_idx++] = ints[1];
                   3625:         irqs[setup_idx]   = 0xff;
                   3626:         return;
                   3627:     }
                   3628:     if (ints[1] == 0) {
                   3629:         disable_gdth_scan = TRUE;
                   3630:         return;
                   3631:     }
                   3632:     printk("GDT: Invalid IRQ (%d) specified\n",ints[1]);
                   3633: }
                   3634: 
                   3635: 
                   3636: #ifdef MODULE
                   3637: Scsi_Host_Template driver_template = GDTH;
                   3638: #include "scsi_module.c"
                   3639: #endif
                   3640: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.