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

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

unix.superglobalmegacorp.com

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