linux-old/drivers/scsi/tmscsim.c
<<
>>
Prefs
   1/***********************************************************************
   2 *      FILE NAME : TMSCSIM.C                                          *
   3 *           BY   : C.L. Huang,  ching@tekram.com.tw                   *
   4 *      Description: Device Driver for Tekram DC-390(T) PCI SCSI       *
   5 *                   Bus Master Host Adapter                           *
   6 * (C)Copyright 1995-1996 Tekram Technology Co., Ltd.                  *
   7 ***********************************************************************/
   8/* (C) Copyright: put under GNU GPL in 10/96  (see README.tmscsim)      *
   9*************************************************************************/
  10/* $Id: tmscsim.c,v 2.60.2.30 2000/12/20 01:07:12 garloff Exp $         */
  11/*      Enhancements and bugfixes by                                    *
  12 *      Kurt Garloff <kurt@garloff.de>  <garloff@suse.de>               *
  13 ***********************************************************************/
  14/*      HISTORY:                                                        *
  15 *                                                                      *
  16 *      REV#    DATE    NAME    DESCRIPTION                             *
  17 *      1.00  96/04/24  CLH     First release                           *
  18 *      1.01  96/06/12  CLH     Fixed bug of Media Change for Removable *
  19 *                              Device, scan all LUN. Support Pre2.0.10 *
  20 *      1.02  96/06/18  CLH     Fixed bug of Command timeout ...        *
  21 *      1.03  96/09/25  KG      Added tmscsim_proc_info()               *
  22 *      1.04  96/10/11  CLH     Updating for support KV 2.0.x           *
  23 *      1.05  96/10/18  KG      Fixed bug in DC390_abort(null ptr deref)*
  24 *      1.06  96/10/25  KG      Fixed module support                    *
  25 *      1.07  96/11/09  KG      Fixed tmscsim_proc_info()               *
  26 *      1.08  96/11/18  KG      Fixed null ptr in DC390_Disconnect()    *
  27 *      1.09  96/11/30  KG      Added register the allocated IO space   *
  28 *      1.10  96/12/05  CLH     Modified tmscsim_proc_info(), and reset *
  29 *                              pending interrupt in DC390_detect()     *
  30 *      1.11  97/02/05  KG/CLH  Fixeds problem with partitions greater  *
  31 *                              than 1GB                                *
  32 *      1.12  98/02/15  MJ      Rewritten PCI probing                   *
  33 *      1.13  98/04/08  KG      Support for non DC390, __initfunc decls,*
  34 *                              changed max devs from 10 to 16          *
  35 *      1.14a 98/05/05  KG      Dynamic DCB allocation, add-single-dev  *
  36 *                              for LUNs if LUN_SCAN (BIOS) not set     *
  37 *                              runtime config using /proc interface    *
  38 *      1.14b 98/05/06  KG      eliminated cli (); sti (); spinlocks    *
  39 *      1.14c 98/05/07  KG      2.0.x compatibility                     *
  40 *      1.20a 98/05/07  KG      changed names of funcs to be consistent *
  41 *                              DC390_ (entry points), dc390_ (internal)*
  42 *                              reworked locking                        *
  43 *      1.20b 98/05/12  KG      bugs: version, kfree, _ctmp             *
  44 *                              debug output                            *
  45 *      1.20c 98/05/12  KG      bugs: kfree, parsing, EEpromDefaults    *
  46 *      1.20d 98/05/14  KG      bugs: list linkage, clear flag after    *
  47 *                              reset on startup, code cleanup          *
  48 *      1.20e 98/05/15  KG      spinlock comments, name space cleanup   *
  49 *                              pLastDCB now part of ACB structure      *
  50 *                              added stats, timeout for 2.1, TagQ bug  *
  51 *                              RESET and INQUIRY interface commands    *
  52 *      1.20f 98/05/18  KG      spinlocks fixes, max_lun fix, free DCBs *
  53 *                              for missing LUNs, pending int           *
  54 *      1.20g 98/05/19  KG      Clean up: Avoid short                   *
  55 *      1.20h 98/05/21  KG      Remove AdaptSCSIID, max_lun ...         *
  56 *      1.20i 98/05/21  KG      Aiiie: Bug with TagQMask                *
  57 *      1.20j 98/05/24  KG      Handle STAT_BUSY, handle pACB->pLinkDCB *
  58 *                              == 0 in remove_dev and DoingSRB_Done    *
  59 *      1.20k 98/05/25  KG      DMA_INT (experimental)                  *
  60 *      1.20l 98/05/27  KG      remove DMA_INT; DMA_IDLE cmds added;    *
  61 *      1.20m 98/06/10  KG      glitch configurable; made some global   *
  62 *                              vars part of ACB; use DC390_readX       *
  63 *      1.20n 98/06/11  KG      startup params                          *
  64 *      1.20o 98/06/15  KG      added TagMaxNum to boot/module params   *
  65 *                              Device Nr -> Idx, TagMaxNum power of 2  *
  66 *      1.20p 98/06/17  KG      Docu updates. Reset depends on settings *
  67 *                              pci_set_master added; 2.0.xx: pcibios_* *
  68 *                              used instead of MechNum things ...      *
  69 *      1.20q 98/06/23  KG      Changed defaults. Added debug code for  *
  70 *                              removable media and fixed it. TagMaxNum *
  71 *                              fixed for DC390. Locking: ACB, DRV for  *
  72 *                              better IRQ sharing. Spelling: Queueing  *
  73 *                              Parsing and glitch_cfg changes. Display *
  74 *                              real SyncSpeed value. Made DisConn      *
  75 *                              functional (!)                          *
  76 *      1.20r 98/06/30  KG      Debug macros, allow disabling DsCn, set *
  77 *                              BIT4 in CtrlR4, EN_PAGE_INT, 2.0 module *
  78 *                              param -1 fixed.                         *
  79 *      1.20s 98/08/20  KG      Debug info on abort(), try to check PCI,*
  80 *                              phys_to_bus instead of phys_to_virt,    *
  81 *                              fixed sel. process, fixed locking,      *
  82 *                              added MODULE_XXX infos, changed IRQ     *
  83 *                              request flags, disable DMA_INT          *
  84 *      1.20t 98/09/07  KG      TagQ report fixed; Write Erase DMA Stat;*
  85 *                              initfunc -> __init; better abort;       *
  86 *                              Timeout for XFER_DONE & BLAST_COMPLETE; *
  87 *                              Allow up to 33 commands being processed *
  88 *      2.0a  98/10/14  KG      Max Cmnds back to 17. DMA_Stat clearing *
  89 *                              all flags. Clear within while() loops   *
  90 *                              in DataIn_0/Out_0. Null ptr in dumpinfo *
  91 *                              for pSRB==0. Better locking during init.*
  92 *                              bios_param() now respects part. table.  *
  93 *      2.0b  98/10/24  KG      Docu fixes. Timeout Msg in DMA Blast.   *
  94 *                              Disallow illegal idx in INQUIRY/REMOVE  *
  95 *      2.0c  98/11/19  KG      Cleaned up detect/init for SMP boxes,   *
  96 *                              Write Erase DMA (1.20t) caused problems *
  97 *      2.0d  98/12/25  KG      Christmas release ;-) Message handling  *
  98 *                              completely reworked. Handle target ini- *
  99 *                              tiated SDTR correctly.                  *
 100 *      2.0d1 99/01/25  KG      Try to handle RESTORE_PTR               *
 101 *      2.0d2 99/02/08  KG      Check for failure of kmalloc, correct   *
 102 *                              inclusion of scsicam.h, DelayReset      *
 103 *      2.0d3 99/05/31  KG      DRIVER_OK -> DID_OK, DID_NO_CONNECT,    *
 104 *                              detect Target mode and warn.            *
 105 *                              pcmd->result handling cleaned up.       *
 106 *      2.0d4 99/06/01  KG      Cleaned selection process. Found bug    *
 107 *                              which prevented more than 16 tags. Now: *
 108 *                              24. SDTR cleanup. Cleaner multi-LUN     *
 109 *                              handling. Don't modify ControlRegs/FIFO *
 110 *                              when connected.                         *
 111 *      2.0d5 99/06/01  KG      Clear DevID, Fix INQUIRY after cfg chg. *
 112 *      2.0d6 99/06/02  KG      Added ADD special command to allow cfg. *
 113 *                              before detection. Reset SYNC_NEGO_DONE  *
 114 *                              after a bus reset.                      *
 115 *      2.0d7 99/06/03  KG      Fixed bugs wrt add,remove commands      *
 116 *      2.0d8 99/06/04  KG      Removed copying of cmnd into CmdBlock.  *
 117 *                              Fixed Oops in _release().               *
 118 *      2.0d9 99/06/06  KG      Also tag queue INQUIRY, T_U_R, ...      *
 119 *                              Allow arb. no. of Tagged Cmnds. Max 32  *
 120 *      2.0d1099/06/20  KG      TagMaxNo changes now honoured! Queueing *
 121 *                              clearified (renamed ..) TagMask handling*
 122 *                              cleaned.                                *
 123 *      2.0d1199/06/28  KG      cmd->result now identical to 2.0d2      *
 124 *      2.0d1299/07/04  KG      Changed order of processing in IRQ      *
 125 *      2.0d1399/07/05  KG      Don't update DCB fields if removed      *
 126 *      2.0d1499/07/05  KG      remove_dev: Move kfree() to the end     *
 127 *      2.0d1599/07/12  KG      use_new_eh_code: 0, ULONG -> UINT where *
 128 *                              appropriate                             *
 129 *      2.0d1699/07/13  KG      Reenable StartSCSI interrupt, Retry msg *
 130 *      2.0d1799/07/15  KG      Remove debug msg. Disable recfg. when   *
 131 *                              there are queued cmnds                  *
 132 *      2.0d1899/07/18  KG      Selection timeout: Don't requeue        *
 133 *      2.0d1999/07/18  KG      Abort: Only call scsi_done if dequeued  *
 134 *      2.0d2099/07/19  KG      Rst_Detect: DoingSRB_Done               *
 135 *      2.0d2199/08/15  KG      dev_id for request/free_irq, cmnd[0] for*
 136 *                              RETRY, SRBdone does DID_ABORT for the   *
 137 *                              cmd passed by DC390_reset()             *
 138 *      2.0d2299/08/25  KG      dev_id fixed. can_queue: 42             *
 139 *      2.0d2399/08/25  KG      Removed some debugging code. dev_id     *
 140 *                              now is set to pACB. Use u8,u16,u32.     *
 141 *      2.0d2499/11/14  KG      Unreg. I/O if failed IRQ alloc. Call    *
 142 *                              done () w/ DID_BAD_TARGET in case of    *
 143 *                              missing DCB. We are old EH!!            *
 144 *      2.0d2500/01/15  KG      2.3.3x compat from Andreas Schultz      *
 145 *                              set unique_id. Disable RETRY message.   *
 146 *      2.0d2600/01/29  KG      Go to new EH.                           *
 147 *      2.0d2700/01/31  KG      ... but maintain 2.0 compat.            *
 148 *                              and fix DCB freeing                     *
 149 *      2.0d2800/02/14  KG      Queue statistics fixed, dump special cmd*
 150 *                              Waiting_Timer for failed StartSCSI      *
 151 *                              New EH: Don't return cmnds to ML on RST *
 152 *                              Use old EH (don't have new EH fns yet)  *
 153 *                              Reset: Unlock, but refuse to queue      *
 154 *                              2.3 __setup function                    *
 155 *      2.0e  00/05/22  KG      Return residual for 2.3                 *
 156 *      2.0e1 00/05/25  KG      Compile fixes for 2.3.99                *
 157 *      2.0e2 00/05/27  KG      Jeff Garzik's pci_enable_device()       *
 158 *      2.0e3 00/09/29  KG      Some 2.4 changes. Don't try Sync Nego   *
 159 *                              before INQUIRY has reported ability.    *
 160 *                              Recognise INQUIRY as scanning command.  *
 161 *      2.0e4 00/10/13  KG      Allow compilation into 2.4 kernel       *
 162 *      2.0e5 00/11/17  KG      Store Inq.flags in DCB                  *
 163 *      2.0e6 00/11/22  KG      2.4 init function (Thx to O.Schumann)   *
 164 *                              2.4 PCI device table (Thx to A.Richter) *
 165 *      2.0e7 00/11/28  KG      Allow overriding of BIOS settings       *
 166 *      2.0f  00/12/20  KG      Handle failed INQUIRYs during scan      *
 167 ***********************************************************************/
 168
 169/* Uncomment SA_INTERRUPT, if the driver refuses to share its IRQ with other devices */
 170#define DC390_IRQ SA_SHIRQ /* | SA_INTERRUPT */
 171
 172/* DEBUG options */
 173//#define DC390_DEBUG0
 174//#define DC390_DEBUG1
 175//#define DC390_DCBDEBUG
 176//#define DC390_PARSEDEBUG
 177//#define DC390_REMOVABLEDEBUG
 178//#define DC390_LOCKDEBUG
 179
 180/* Debug definitions */
 181#ifdef DC390_DEBUG0
 182# define DEBUG0(x) x;
 183#else
 184# define DEBUG0(x)
 185#endif
 186#ifdef DC390_DEBUG1
 187# define DEBUG1(x) x;
 188#else
 189# define DEBUG1(x)
 190#endif
 191#ifdef DC390_DCBDEBUG
 192# define DCBDEBUG(x) x;
 193#else
 194# define DCBDEBUG(x)
 195#endif
 196#ifdef DC390_PARSEDEBUG
 197# define PARSEDEBUG(x) x;
 198#else
 199# define PARSEDEBUG(x)
 200#endif
 201#ifdef DC390_REMOVABLEDEBUG
 202# define REMOVABLEDEBUG(x) x;
 203#else
 204# define REMOVABLEDEBUG(x)
 205#endif
 206#define DCBDEBUG1(x)
 207
 208/* Includes */
 209#include <linux/module.h>
 210#include <asm/dma.h>
 211#include <asm/io.h>
 212#include <asm/system.h>
 213#include <linux/delay.h>
 214#include <linux/signal.h>
 215#include <linux/sched.h>
 216#include <linux/errno.h>
 217#include <linux/kernel.h>
 218#include <linux/ioport.h>
 219#include <linux/pci.h>
 220#include <linux/proc_fs.h>
 221#include <linux/string.h>
 222#include <linux/ctype.h>
 223#include <linux/mm.h>
 224#include <linux/config.h>
 225#include <linux/version.h>
 226#include <linux/blk.h>
 227#include <linux/timer.h>
 228
 229#include "scsi.h"
 230#include "hosts.h"
 231#include "constants.h"
 232#include "sd.h"
 233#include <linux/stat.h>
 234#include <scsi/scsicam.h>
 235
 236#include "dc390.h"
 237
 238#define PCI_DEVICE_ID_AMD53C974         PCI_DEVICE_ID_AMD_SCSI
 239
 240/* Locking */
 241
 242/* Note: Starting from 2.1.9x, the mid-level scsi code issues a 
 243 * spinlock_irqsave (&io_request_lock) before calling the driver's 
 244 * routines, so we don't need to lock, except in the IRQ handler.
 245 * The policy 3, let the midlevel scsi code do the io_request_locks
 246 * and us locking on a driver specific lock, shouldn't hurt anybody; it
 247 * just causes a minor performance degradation for setting the locks.
 248 */
 249
 250/* spinlock things
 251 * level 3: lock on both adapter specific locks and (global) io_request_lock
 252 * level 2: lock on adapter specific locks only
 253 * level 1: rely on the locking of the mid level code (io_request_lock)
 254 * undef  : traditional save_flags; cli; restore_flags;
 255 */
 256
 257//#define DEBUG_SPINLOCKS 2     /* Set to 0, 1 or 2 in include/linux/spinlock.h */
 258
 259#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30)
 260# include <linux/init.h>
 261#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30)
 262# include <linux/spinlock.h>
 263#else
 264# include <asm/spinlock.h>
 265#endif
 266#endif
 267
 268
 269#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93) 
 270# define USE_SPINLOCKS 1
 271# define NEW_PCI 1
 272#else
 273# undef NEW_PCI
 274# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30)
 275#  define USE_SPINLOCKS 2
 276# endif
 277#endif
 278
 279#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,99)
 280static struct pci_device_id tmscsim_pci_tbl[] __initdata = {
 281        {
 282                vendor: PCI_VENDOR_ID_AMD,
 283                device: PCI_DEVICE_ID_AMD53C974,
 284                subvendor: PCI_ANY_ID,
 285                subdevice: PCI_ANY_ID,
 286        },
 287        { }             /* Terminating entry */
 288};
 289MODULE_DEVICE_TABLE(pci, tmscsim_pci_tbl);
 290#endif
 291        
 292#ifdef USE_SPINLOCKS
 293
 294# if USE_SPINLOCKS == 3 /* both */
 295
 296#  if defined (CONFIG_SMP) || DEBUG_SPINLOCKS > 0
 297#   define DC390_LOCKA_INIT { spinlock_t __unlocked = SPIN_LOCK_UNLOCKED; pACB->lock = __unlocked; };
 298#  else
 299#   define DC390_LOCKA_INIT
 300#  endif
 301   spinlock_t dc390_drvlock = SPIN_LOCK_UNLOCKED;
 302
 303#  define DC390_AFLAGS unsigned long aflags;
 304#  define DC390_IFLAGS unsigned long iflags;
 305#  define DC390_DFLAGS unsigned long dflags; 
 306
 307#  define DC390_LOCK_IO spin_lock_irqsave (&io_request_lock, iflags)
 308#  define DC390_UNLOCK_IO spin_unlock_irqrestore (&io_request_lock, iflags)
 309
 310#  define DC390_LOCK_DRV spin_lock_irqsave (&dc390_drvlock, dflags)
 311#  define DC390_UNLOCK_DRV spin_unlock_irqrestore (&dc390_drvlock, dflags)
 312#  define DC390_LOCK_DRV_NI spin_lock (&dc390_drvlock)
 313#  define DC390_UNLOCK_DRV_NI spin_unlock (&dc390_drvlock)
 314
 315#  define DC390_LOCK_ACB spin_lock_irqsave (&(pACB->lock), aflags)
 316#  define DC390_UNLOCK_ACB spin_unlock_irqrestore (&(pACB->lock), aflags)
 317#  define DC390_LOCK_ACB_NI spin_lock (&(pACB->lock))
 318#  define DC390_UNLOCK_ACB_NI spin_unlock (&(pACB->lock))
 319//#  define DC390_LOCKA_INIT spin_lock_init (&(pACB->lock))
 320
 321# else
 322
 323#  if USE_SPINLOCKS == 2 /* adapter specific locks */
 324
 325#   if defined (CONFIG_SMP) || DEBUG_SPINLOCKS > 0
 326#    define DC390_LOCKA_INIT { spinlock_t __unlocked = SPIN_LOCK_UNLOCKED; pACB->lock = __unlocked; };
 327#   else
 328#    define DC390_LOCKA_INIT
 329#   endif
 330    spinlock_t dc390_drvlock = SPIN_LOCK_UNLOCKED;
 331#   define DC390_AFLAGS unsigned long aflags;
 332#   define DC390_IFLAGS 
 333#  define DC390_DFLAGS unsigned long dflags; 
 334#   define DC390_LOCK_IO /* spin_lock_irqsave (&io_request_lock, iflags) */
 335#   define DC390_UNLOCK_IO /* spin_unlock_irqrestore (&io_request_lock, iflags) */
 336#   define DC390_LOCK_DRV spin_lock_irqsave (&dc390_drvlock, dflags)
 337#   define DC390_UNLOCK_DRV spin_unlock_irqrestore (&dc390_drvlock, dflags)
 338#   define DC390_LOCK_DRV_NI spin_lock (&dc390_drvlock)
 339#   define DC390_UNLOCK_DRV_NI spin_unlock (&dc390_drvlock)
 340#   define DC390_LOCK_ACB spin_lock_irqsave (&(pACB->lock), aflags)
 341#   define DC390_UNLOCK_ACB spin_unlock_irqrestore (&(pACB->lock), aflags)
 342#   define DC390_LOCK_ACB_NI spin_lock (&(pACB->lock))
 343#   define DC390_UNLOCK_ACB_NI spin_unlock (&(pACB->lock))
 344//#   define DC390_LOCKA_INIT spin_lock_init (&(pACB->lock))
 345
 346#  else /* USE_SPINLOCKS == 1: global lock io_request_lock */
 347
 348#   define DC390_AFLAGS 
 349#   define DC390_IFLAGS unsigned long iflags;
 350#   define DC390_DFLAGS unsigned long dflags; 
 351    spinlock_t dc390_drvlock = SPIN_LOCK_UNLOCKED;
 352#   define DC390_LOCK_IO spin_lock_irqsave (&io_request_lock, iflags)
 353#   define DC390_UNLOCK_IO spin_unlock_irqrestore (&io_request_lock, iflags)
 354#   define DC390_LOCK_DRV spin_lock_irqsave (&dc390_drvlock, dflags)
 355#   define DC390_UNLOCK_DRV spin_unlock_irqrestore (&dc390_drvlock, dflags)
 356#   define DC390_LOCK_DRV_NI spin_lock (&dc390_drvlock)
 357#   define DC390_UNLOCK_DRV_NI spin_unlock (&dc390_drvlock)
 358#   define DC390_LOCK_ACB /* DC390_LOCK_IO */
 359#   define DC390_UNLOCK_ACB /* DC390_UNLOCK_IO */
 360#   define DC390_LOCK_ACB_NI /* spin_lock (&(pACB->lock)) */
 361#   define DC390_UNLOCK_ACB_NI /* spin_unlock (&(pACB->lock)) */
 362#   define DC390_LOCKA_INIT /* DC390_LOCKA_INIT */
 363
 364#  endif /* 2 */
 365# endif /* 3 */
 366
 367#else /* USE_SPINLOCKS undefined */
 368
 369# define DC390_AFLAGS unsigned long aflags;
 370# define DC390_IFLAGS unsigned long iflags;
 371# define DC390_DFLAGS unsigned long dflags; 
 372# define DC390_LOCK_IO save_flags (iflags); cli ()
 373# define DC390_UNLOCK_IO restore_flags (iflags)
 374# define DC390_LOCK_DRV save_flags (dflags); cli ()
 375# define DC390_UNLOCK_DRV restore_flags (dflags)
 376# define DC390_LOCK_DRV_NI
 377# define DC390_UNLOCK_DRV_NI
 378# define DC390_LOCK_ACB save_flags (aflags); cli ()
 379# define DC390_UNLOCK_ACB restore_flags (aflags)
 380# define DC390_LOCK_ACB_NI
 381# define DC390_UNLOCK_ACB_NI
 382# define DC390_LOCKA_INIT
 383#endif /* def */
 384
 385
 386/* These macros are used for uniform access to 2.0.x and 2.1.x PCI config space*/
 387
 388#ifdef NEW_PCI
 389# define PDEV pdev
 390# define PDEVDECL struct pci_dev *pdev
 391# define PDEVDECL0 struct pci_dev *pdev = NULL
 392# define PDEVDECL1 struct pci_dev *pdev
 393# define PDEVSET pACB->pdev=pdev
 394# define PDEVSET1 pdev=pACB->pdev
 395# define PCI_WRITE_CONFIG_BYTE(pd, rv, bv) pci_write_config_byte (pd, rv, bv)
 396# define PCI_READ_CONFIG_BYTE(pd, rv, bv) pci_read_config_byte (pd, rv, bv)
 397# define PCI_WRITE_CONFIG_WORD(pd, rv, bv) pci_write_config_word (pd, rv, bv)
 398# define PCI_READ_CONFIG_WORD(pd, rv, bv) pci_read_config_word (pd, rv, bv)
 399# define PCI_BUS_DEV pdev->bus->number, pdev->devfn
 400# define PCI_PRESENT pci_present ()
 401# define PCI_SET_MASTER pci_set_master (pdev)
 402# define PCI_FIND_DEVICE(vend, id) (pdev = pci_find_device (vend, id, pdev))
 403#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,10)
 404# define PCI_GET_IO_AND_IRQ io_port = pci_resource_start (pdev, 0); irq = pdev->irq
 405#else
 406# define PCI_GET_IO_AND_IRQ io_port = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; irq = pdev->irq
 407#endif
 408#else
 409# include <linux/bios32.h>
 410# define PDEV pbus, pdevfn
 411# define PDEVDECL UCHAR pbus, UCHAR pdevfn
 412# define PDEVDECL0 UCHAR pbus = 0; UCHAR pdevfn = 0; USHORT pci_index = 0; int error
 413# define PDEVDECL1 UCHAR pbus; UCHAR pdevfn /*; USHORT pci_index */
 414# define PDEVSET pACB->pbus=pbus; pACB->pdevfn=pdevfn /*; pACB->pci_index=pci_index */
 415# define PDEVSET1 pbus=pACB->pbus; pdevfn=pACB->pdevfn /*; pci_index=pACB->pci_index */
 416# define PCI_WRITE_CONFIG_BYTE(pd, rv, bv) pcibios_write_config_byte (pd, rv, bv)
 417# define PCI_READ_CONFIG_BYTE(pd, rv, bv) pcibios_read_config_byte (pd, rv, bv)
 418# define PCI_WRITE_CONFIG_WORD(pd, rv, bv) pcibios_write_config_word (pd, rv, bv)
 419# define PCI_READ_CONFIG_WORD(pd, rv, bv) pcibios_read_config_word (pd, rv, bv)
 420# define PCI_BUS_DEV pbus, pdevfn
 421# define PCI_PRESENT pcibios_present ()
 422# define PCI_SET_MASTER dc390_set_master (pbus, pdevfn)
 423# define PCI_FIND_DEVICE(vend, id) (!pcibios_find_device (vend, id, pci_index++, &pbus, &pdevfn))
 424# define PCI_GET_IO_AND_IRQ error = pcibios_read_config_dword (pbus, pdevfn, PCI_BASE_ADDRESS_0, &io_port);     \
 425 error |= pcibios_read_config_byte (pbus, pdevfn, PCI_INTERRUPT_LINE, &irq);    \
 426 io_port &= 0xfffe;     \
 427 if (error) { printk (KERN_ERR "DC390_detect: Error reading PCI config registers!\n"); continue; }
 428#endif 
 429
 430#include "tmscsim.h"
 431
 432#ifndef __init
 433# define __init
 434#endif
 435
 436UCHAR dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB );
 437void dc390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
 438void dc390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
 439static void dc390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
 440static void dc390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
 441static void dc390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
 442void dc390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
 443static void dc390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
 444static void dc390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
 445void dc390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
 446static void dc390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
 447void dc390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
 448static void dc390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
 449static void dc390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
 450static void dc390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus);
 451
 452static void dc390_SetXferRate( PACB pACB, PDCB pDCB );
 453void dc390_Disconnect( PACB pACB );
 454void dc390_Reselect( PACB pACB );
 455void dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB );
 456void dc390_DoingSRB_Done( PACB pACB, PSCSICMD cmd );
 457static void dc390_ScsiRstDetect( PACB pACB );
 458static void dc390_ResetSCSIBus( PACB pACB );
 459static void __inline__ dc390_RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB );
 460static void __inline__ dc390_InvalidCmd( PACB pACB );
 461static void __inline__ dc390_EnableMsgOut_Abort (PACB, PSRB);
 462static void dc390_remove_dev (PACB pACB, PDCB pDCB);
 463void do_DC390_Interrupt( int, void *, struct pt_regs *);
 464
 465int    dc390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, UCHAR index );
 466void   dc390_initDCB( PACB pACB, PDCB *ppDCB, UCHAR id, UCHAR lun);
 467void   dc390_updateDCB (PACB pACB, PDCB pDCB);
 468
 469#ifdef MODULE
 470 static int DC390_release(struct Scsi_Host *host);
 471 static int dc390_shutdown (struct Scsi_Host *host);
 472#endif
 473
 474
 475//static PSHT   dc390_pSHT_start = NULL;
 476//static PSH    dc390_pSH_start = NULL;
 477//static PSH    dc390_pSH_current = NULL;
 478static PACB     dc390_pACB_start= NULL;
 479static PACB     dc390_pACB_current = NULL;
 480static ULONG    dc390_lastabortedpid = 0;
 481static UINT     dc390_laststatus = 0;
 482static UCHAR    dc390_adapterCnt = 0;
 483
 484/* Startup values, to be overriden on the commandline */
 485int tmscsim[] = {-2, -2, -2, -2, -2, -2};
 486
 487# if defined(MODULE) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30)
 488MODULE_PARM(tmscsim, "1-6i");
 489MODULE_PARM_DESC(tmscsim, "Host SCSI ID, Speed (0=10MHz), Device Flags, Adapter Flags, Max Tags (log2(tags)-1), DelayReset (s)");
 490# endif
 491
 492#if defined(MODULE) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30)
 493MODULE_AUTHOR("C.L. Huang / Kurt Garloff");
 494MODULE_DESCRIPTION("SCSI host adapter driver for Tekram DC390 and other AMD53C974A based PCI SCSI adapters");
 495MODULE_LICENSE("GPL");
 496
 497MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
 498#endif
 499
 500static PVOID dc390_phase0[]={
 501       dc390_DataOut_0,
 502       dc390_DataIn_0,
 503       dc390_Command_0,
 504       dc390_Status_0,
 505       dc390_Nop_0,
 506       dc390_Nop_0,
 507       dc390_MsgOut_0,
 508       dc390_MsgIn_0,
 509       dc390_Nop_1
 510       };
 511
 512static PVOID dc390_phase1[]={
 513       dc390_DataOutPhase,
 514       dc390_DataInPhase,
 515       dc390_CommandPhase,
 516       dc390_StatusPhase,
 517       dc390_Nop_0,
 518       dc390_Nop_0,
 519       dc390_MsgOutPhase,
 520       dc390_MsgInPhase,
 521       dc390_Nop_1
 522       };
 523
 524#ifdef DC390_DEBUG1
 525static char* dc390_p0_str[] = {
 526       "dc390_DataOut_0",
 527       "dc390_DataIn_0",
 528       "dc390_Command_0",
 529       "dc390_Status_0",
 530       "dc390_Nop_0",
 531       "dc390_Nop_0",
 532       "dc390_MsgOut_0",
 533       "dc390_MsgIn_0",
 534       "dc390_Nop_1"
 535       };
 536     
 537static char* dc390_p1_str[] = {
 538       "dc390_DataOutPhase",
 539       "dc390_DataInPhase",
 540       "dc390_CommandPhase",
 541       "dc390_StatusPhase",
 542       "dc390_Nop_0",
 543       "dc390_Nop_0",
 544       "dc390_MsgOutPhase",
 545       "dc390_MsgInPhase",
 546       "dc390_Nop_1"
 547       };
 548#endif   
 549
 550/* Devices erroneously pretending to be able to do TagQ */
 551UCHAR  dc390_baddevname1[2][28] ={
 552       "SEAGATE ST3390N         9546",
 553       "HP      C3323-300       4269"};
 554#define BADDEVCNT       2
 555
 556static char*  dc390_adapname = "DC390";
 557UCHAR  dc390_eepromBuf[MAX_ADAPTER_NUM][EE_LEN];
 558UCHAR  dc390_clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20};
 559UCHAR  dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20};
 560
 561#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,30)
 562struct proc_dir_entry   DC390_proc_scsi_tmscsim ={
 563       PROC_SCSI_DC390T, 7 ,"tmscsim",
 564       S_IFDIR | S_IRUGO | S_IXUGO, 2
 565       };
 566#endif
 567
 568/***********************************************************************
 569 * Functions for access to DC390 EEPROM
 570 * and some to emulate it
 571 *
 572 **********************************************************************/
 573
 574
 575static void __init dc390_EnDisableCE( UCHAR mode, PDEVDECL, PUCHAR regval )
 576{
 577    UCHAR bval;
 578
 579    bval = 0;
 580    if(mode == ENABLE_CE)
 581        *regval = 0xc0;
 582    else
 583        *regval = 0x80;
 584    PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
 585    if(mode == DISABLE_CE)
 586        PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
 587    udelay(160);
 588}
 589
 590
 591/* Override EEprom values with explicitly set values */
 592static void __init dc390_EEprom_Override (UCHAR index)
 593{
 594    PUCHAR ptr;
 595    UCHAR  id;
 596    ptr = (PUCHAR) dc390_eepromBuf[index];
 597    
 598    /* Adapter Settings */
 599    if (tmscsim[0] != -2)
 600        ptr[EE_ADAPT_SCSI_ID] = (UCHAR)tmscsim[0];      /* Adapter ID */
 601    if (tmscsim[3] != -2)
 602        ptr[EE_MODE2] = (UCHAR)tmscsim[3];
 603    if (tmscsim[5] != -2)
 604        ptr[EE_DELAY] = tmscsim[5];                     /* Reset delay */
 605    if (tmscsim[4] != -2)
 606        ptr[EE_TAG_CMD_NUM] = (UCHAR)tmscsim[4];        /* Tagged Cmds */
 607    
 608    /* Device Settings */
 609    for (id = 0; id < MAX_SCSI_ID; id++)
 610    {
 611        if (tmscsim[2] != -2)
 612                ptr[id<<2] = (UCHAR)tmscsim[2];         /* EE_MODE1 */
 613        if (tmscsim[1] != -2)
 614                ptr[(id<<2) + 1] = (UCHAR)tmscsim[1];   /* EE_Speed */
 615    };
 616}
 617
 618/* Handle "-1" case */
 619static void __init dc390_check_for_safe_settings (void)
 620{
 621        if (tmscsim[0] == -1 || tmscsim[0] > 15) /* modules-2.0.0 passes -1 as string */
 622        {
 623                tmscsim[0] = 7; tmscsim[1] = 4;
 624                tmscsim[2] = 0x09; tmscsim[3] = 0x0f;
 625                tmscsim[4] = 2; tmscsim[5] = 10;
 626                printk (KERN_INFO "DC390: Using safe settings.\n");
 627        }
 628}
 629
 630
 631#ifndef CONFIG_SCSI_DC390T_NOGENSUPP
 632int __initdata tmscsim_def[] = {7, 0 /* 10MHz */,
 633                PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_
 634                | SYNC_NEGO_ | TAG_QUEUEING_,
 635                MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION
 636                /* | NO_SEEK */
 637# ifdef CONFIG_SCSI_MULTI_LUN
 638                | LUN_CHECK
 639# endif
 640                , 3 /* 16 Tags per LUN */, 1 /* s delay after Reset */ };
 641
 642/* Copy defaults over set values where missing */
 643static void __init dc390_fill_with_defaults (void)
 644{
 645        int i;
 646        PARSEDEBUG(printk(KERN_INFO "DC390: setup %08x %08x %08x %08x %08x %08x\n", tmscsim[0],\
 647                      tmscsim[1], tmscsim[2], tmscsim[3], tmscsim[4], tmscsim[5]);)
 648        for (i = 0; i < 6; i++)
 649        {
 650                if (tmscsim[i] < 0 || tmscsim[i] > 255)
 651                        tmscsim[i] = tmscsim_def[i];
 652        }
 653        /* Sanity checks */
 654        if (tmscsim[0] >   7) tmscsim[0] =   7;
 655        if (tmscsim[1] >   7) tmscsim[1] =   4;
 656        if (tmscsim[4] >   5) tmscsim[4] =   4;
 657        if (tmscsim[5] > 180) tmscsim[5] = 180;
 658};
 659#endif
 660
 661/* Override defaults on cmdline:
 662 * tmscsim: AdaptID, MaxSpeed (Index), DevMode (Bitmapped), AdaptMode (Bitmapped)
 663 */
 664#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13)
 665int __init dc390_setup (char *str)
 666{       
 667        int ints[8];
 668        int i, im;
 669        (void)get_options (str, ARRAY_SIZE(ints), ints);
 670        im = ints[0];
 671        if (im > 6)
 672        {
 673                printk (KERN_NOTICE "DC390: ignore extra params!\n");
 674                im = 6;
 675        };
 676        for (i = 0; i < im; i++)
 677                tmscsim[i] = ints[i+1];
 678        /* dc390_checkparams (); */
 679        return 1;
 680};
 681#ifndef MODULE
 682__setup("tmscsim=", dc390_setup);
 683#endif
 684
 685#else
 686void __init dc390_setup (char *str, int *ints)
 687{
 688        int i, im;
 689        im = ints[0];
 690        if (im > 6)
 691        {
 692                printk (KERN_NOTICE "DC390: ignore extra params!\n");
 693                im = 6;
 694        };
 695        for (i = 0; i < im; i++)
 696                tmscsim[i] = ints[i+1];
 697        /* dc390_checkparams (); */
 698};
 699#endif
 700
 701
 702
 703static void __init dc390_EEpromOutDI( PDEVDECL, PUCHAR regval, UCHAR Carry )
 704{
 705    UCHAR bval;
 706
 707    bval = 0;
 708    if(Carry)
 709    {
 710        bval = 0x40;
 711        *regval = 0x80;
 712        PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
 713    }
 714    udelay(160);
 715    bval |= 0x80;
 716    PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
 717    udelay(160);
 718    bval = 0;
 719    PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
 720    udelay(160);
 721}
 722
 723
 724static UCHAR __init dc390_EEpromInDO( PDEVDECL )
 725{
 726    UCHAR bval;
 727
 728    PCI_WRITE_CONFIG_BYTE(PDEV, 0x80, 0x80);
 729    udelay(160);
 730    PCI_WRITE_CONFIG_BYTE(PDEV, 0x80, 0x40);
 731    udelay(160);
 732    PCI_READ_CONFIG_BYTE(PDEV, 0x00, &bval);
 733    if(bval == 0x22)
 734        return(1);
 735    else
 736        return(0);
 737}
 738
 739
 740static USHORT __init dc390_EEpromGetData1( PDEVDECL )
 741{
 742    UCHAR i;
 743    UCHAR carryFlag;
 744    USHORT wval;
 745
 746    wval = 0;
 747    for(i=0; i<16; i++)
 748    {
 749        wval <<= 1;
 750        carryFlag = dc390_EEpromInDO(PDEV);
 751        wval |= carryFlag;
 752    }
 753    return(wval);
 754}
 755
 756
 757static void __init dc390_Prepare( PDEVDECL, PUCHAR regval, UCHAR EEpromCmd )
 758{
 759    UCHAR i,j;
 760    UCHAR carryFlag;
 761
 762    carryFlag = 1;
 763    j = 0x80;
 764    for(i=0; i<9; i++)
 765    {
 766        dc390_EEpromOutDI(PDEV,regval,carryFlag);
 767        carryFlag = (EEpromCmd & j) ? 1 : 0;
 768        j >>= 1;
 769    }
 770}
 771
 772
 773static void __init dc390_ReadEEprom( PDEVDECL, PUSHORT ptr)
 774{
 775    UCHAR   regval,cmd;
 776    UCHAR   i;
 777
 778    cmd = EEPROM_READ;
 779    for(i=0; i<0x40; i++)
 780    {
 781        dc390_EnDisableCE(ENABLE_CE, PDEV, &regval);
 782        dc390_Prepare(PDEV, &regval, cmd++);
 783        *ptr++ = dc390_EEpromGetData1(PDEV);
 784        dc390_EnDisableCE(DISABLE_CE, PDEV, &regval);
 785    }
 786}
 787
 788
 789static void __init dc390_interpret_delay (UCHAR index)
 790{
 791    char interpd [] = {1,3,5,10,16,30,60,120};
 792    dc390_eepromBuf[index][EE_DELAY] = interpd [dc390_eepromBuf[index][EE_DELAY]];
 793};
 794
 795static UCHAR __init dc390_CheckEEpromCheckSum( PDEVDECL, UCHAR index )
 796{
 797    UCHAR  i;
 798    char  EEbuf[128];
 799    USHORT wval, *ptr = (PUSHORT)EEbuf;
 800
 801    dc390_ReadEEprom( PDEV, ptr );
 802    memcpy (dc390_eepromBuf[index], EEbuf, EE_ADAPT_SCSI_ID);
 803    memcpy (&dc390_eepromBuf[index][EE_ADAPT_SCSI_ID], 
 804            &EEbuf[REAL_EE_ADAPT_SCSI_ID], EE_LEN - EE_ADAPT_SCSI_ID);
 805    dc390_interpret_delay (index);
 806    
 807    wval = 0;
 808    for(i=0; i<0x40; i++, ptr++)
 809        wval += *ptr;
 810    return (wval == 0x1234 ? 0 : 1);
 811}
 812
 813
 814/***********************************************************************
 815 * Functions for the management of the internal structures 
 816 * (DCBs, SRBs, Queueing)
 817 *
 818 **********************************************************************/
 819static PDCB __inline__ dc390_findDCB ( PACB pACB, UCHAR id, UCHAR lun)
 820{
 821   PDCB pDCB = pACB->pLinkDCB; if (!pDCB) return 0;
 822   while (pDCB->TargetID != id || pDCB->TargetLUN != lun)
 823     {
 824        pDCB = pDCB->pNextDCB;
 825        if (pDCB == pACB->pLinkDCB)
 826          {
 827             DCBDEBUG(printk (KERN_WARNING "DC390: DCB not found (DCB=%p, DCBmap[%2x]=%2x)\n",
 828                     pDCB, id, pACB->DCBmap[id]);)
 829             return 0;
 830          }
 831     };
 832   DCBDEBUG1( printk (KERN_DEBUG "DCB %p (%02x,%02x) found.\n", \
 833                      pDCB, pDCB->TargetID, pDCB->TargetLUN);)
 834   return pDCB;
 835};
 836
 837/* Queueing philosphy:
 838 * There are a couple of lists:
 839 * - Query: Contains the Scsi Commands not yet turned into SRBs (per ACB)
 840 *   (Note: For new EH, it is unnecessary!)
 841 * - Waiting: Contains a list of SRBs not yet sent (per DCB)
 842 * - Free: List of free SRB slots
 843 * 
 844 * If there are no waiting commands for the DCB, the new one is sent to the bus
 845 * otherwise the oldest one is taken from the Waiting list and the new one is 
 846 * queued to the Waiting List
 847 * 
 848 * Lists are managed using two pointers and eventually a counter
 849 */
 850
 851
 852#if 0
 853/* Look for a SCSI cmd in a SRB queue */
 854static PSRB dc390_find_cmd_in_SRBq (PSCSICMD cmd, PSRB queue)
 855{
 856    PSRB q = queue;
 857    while (q)
 858    {
 859        if (q->pcmd == cmd) return q;
 860        q = q->pNextSRB;
 861        if (q == queue) return 0;
 862    }
 863    return q;
 864};
 865#endif
 866    
 867
 868/* Append to Query List */
 869static void dc390_Query_append( PSCSICMD cmd, PACB pACB )
 870{
 871    DEBUG0(printk ("DC390: Append cmd %li to Query\n", cmd->pid);)
 872    if( !pACB->QueryCnt )
 873        pACB->pQueryHead = cmd;
 874    else
 875        pACB->pQueryTail->next = cmd;
 876
 877    pACB->pQueryTail = cmd;
 878    pACB->QueryCnt++;
 879    pACB->CmdOutOfSRB++;
 880    cmd->next = NULL;
 881}
 882
 883
 884/* Return next cmd from Query list */
 885static PSCSICMD dc390_Query_get ( PACB pACB )
 886{
 887    PSCSICMD  pcmd;
 888
 889    pcmd = pACB->pQueryHead;
 890    if (!pcmd) return pcmd;
 891    DEBUG0(printk ("DC390: Get cmd %li from Query\n", pcmd->pid);)
 892    pACB->pQueryHead = pcmd->next;
 893    pcmd->next = NULL;
 894    if (!pACB->pQueryHead) pACB->pQueryTail = NULL;
 895    pACB->QueryCnt--;
 896    return( pcmd );
 897}
 898
 899
 900/* Return next free SRB */
 901static __inline__ PSRB dc390_Free_get ( PACB pACB )
 902{
 903    PSRB   pSRB;
 904
 905    pSRB = pACB->pFreeSRB;
 906    DEBUG0(printk ("DC390: Get Free SRB %p\n", pSRB);)
 907    if( pSRB )
 908    {
 909        pACB->pFreeSRB = pSRB->pNextSRB;
 910        pSRB->pNextSRB = NULL;
 911    }
 912
 913    return( pSRB );
 914}
 915
 916/* Insert SRB oin top of free list */
 917static __inline__ void dc390_Free_insert (PACB pACB, PSRB pSRB)
 918{
 919    DEBUG0(printk ("DC390: Free SRB %p\n", pSRB);)
 920    pSRB->pNextSRB = pACB->pFreeSRB;
 921    pACB->pFreeSRB = pSRB;
 922}
 923
 924
 925/* Inserts a SRB to the top of the Waiting list */
 926static __inline__ void dc390_Waiting_insert ( PDCB pDCB, PSRB pSRB )
 927{
 928    DEBUG0(printk ("DC390: Insert pSRB %p cmd %li to Waiting\n", pSRB, pSRB->pcmd->pid);)
 929    pSRB->pNextSRB = pDCB->pWaitingSRB;
 930    if (!pDCB->pWaitingSRB)
 931        pDCB->pWaitLast = pSRB;
 932    pDCB->pWaitingSRB = pSRB;
 933    pDCB->WaitSRBCnt++;
 934}
 935
 936
 937/* Queue SRB to waiting list */
 938static __inline__ void dc390_Waiting_append ( PDCB pDCB, PSRB pSRB)
 939{
 940    DEBUG0(printk ("DC390: Append pSRB %p cmd %li to Waiting\n", pSRB, pSRB->pcmd->pid);)
 941    if( pDCB->pWaitingSRB )
 942        pDCB->pWaitLast->pNextSRB = pSRB;
 943    else
 944        pDCB->pWaitingSRB = pSRB;
 945
 946    pDCB->pWaitLast = pSRB;
 947    pSRB->pNextSRB = NULL;
 948    pDCB->WaitSRBCnt++;
 949    pDCB->pDCBACB->CmdInQ++;
 950}
 951
 952static __inline__ void dc390_Going_append (PDCB pDCB, PSRB pSRB)
 953{
 954    pDCB->GoingSRBCnt++;
 955    DEBUG0(printk("DC390: Append SRB %p to Going\n", pSRB);)
 956    /* Append to the list of Going commands */
 957    if( pDCB->pGoingSRB )
 958        pDCB->pGoingLast->pNextSRB = pSRB;
 959    else
 960        pDCB->pGoingSRB = pSRB;
 961
 962    pDCB->pGoingLast = pSRB;
 963    /* No next one in sent list */
 964    pSRB->pNextSRB = NULL;
 965};
 966
 967static __inline__ void dc390_Going_remove (PDCB pDCB, PSRB pSRB)
 968{
 969   DEBUG0(printk("DC390: Remove SRB %p from Going\n", pSRB);)
 970   if (pSRB == pDCB->pGoingSRB)
 971        pDCB->pGoingSRB = pSRB->pNextSRB;
 972   else
 973     {
 974        PSRB psrb = pDCB->pGoingSRB;
 975        while (psrb && psrb->pNextSRB != pSRB)
 976          psrb = psrb->pNextSRB;
 977        if (!psrb) 
 978          { printk (KERN_ERR "DC390: Remove non-ex. SRB %p from Going!\n", pSRB); return; }
 979        psrb->pNextSRB = pSRB->pNextSRB;
 980        if (pSRB == pDCB->pGoingLast)
 981          pDCB->pGoingLast = psrb;
 982     }
 983   pDCB->GoingSRBCnt--;
 984};
 985
 986/* Moves SRB from Going list to the top of Waiting list */
 987static void dc390_Going_to_Waiting ( PDCB pDCB, PSRB pSRB )
 988{
 989    DEBUG0(printk(KERN_INFO "DC390: Going_to_Waiting (SRB %p) pid = %li\n", pSRB, pSRB->pcmd->pid);)
 990    /* Remove SRB from Going */
 991    dc390_Going_remove (pDCB, pSRB);
 992    /* Insert on top of Waiting */
 993    dc390_Waiting_insert (pDCB, pSRB);
 994    /* Tag Mask must be freed elsewhere ! (KG, 99/06/18) */
 995}
 996
 997/* Moves first SRB from Waiting list to Going list */
 998static __inline__ void dc390_Waiting_to_Going ( PDCB pDCB, PSRB pSRB )
 999{       
1000        /* Remove from waiting list */
1001        DEBUG0(printk("DC390: Remove SRB %p from head of Waiting\n", pSRB);)
1002        pDCB->pWaitingSRB = pSRB->pNextSRB;
1003        if( !pDCB->pWaitingSRB ) pDCB->pWaitLast = NULL;
1004        pDCB->WaitSRBCnt--;
1005        dc390_Going_append (pDCB, pSRB);
1006}
1007
1008/* 2.0 timer compatibility */
1009#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,30)
1010 static inline int timer_pending(struct timer_list * timer)
1011 {
1012        return timer->prev != NULL;
1013 }
1014 #define time_after(a,b)         ((long)(b) - (long)(a) < 0)
1015 #define time_before(a,b)        time_after(b,a)
1016#endif
1017
1018void DC390_waiting_timed_out (unsigned long ptr);
1019/* Sets the timer to wake us up */
1020static void dc390_waiting_timer (PACB pACB, unsigned long to)
1021{
1022        if (timer_pending (&pACB->Waiting_Timer)) return;
1023        init_timer (&pACB->Waiting_Timer);
1024        pACB->Waiting_Timer.function = DC390_waiting_timed_out;
1025        pACB->Waiting_Timer.data = (unsigned long)pACB;
1026        if (time_before (jiffies + to, pACB->pScsiHost->last_reset))
1027                pACB->Waiting_Timer.expires = pACB->pScsiHost->last_reset + 1;
1028        else
1029                pACB->Waiting_Timer.expires = jiffies + to + 1;
1030        add_timer (&pACB->Waiting_Timer);
1031}
1032
1033
1034/* Send the next command from the waiting list to the bus */
1035static void dc390_Waiting_process ( PACB pACB )
1036{
1037    PDCB   ptr, ptr1;
1038    PSRB   pSRB;
1039
1040    if( (pACB->pActiveDCB) || (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) )
1041        return;
1042    if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer);
1043    ptr = pACB->pDCBRunRobin;
1044    if( !ptr )
1045      {
1046        ptr = pACB->pLinkDCB;
1047        pACB->pDCBRunRobin = ptr;
1048      }
1049    ptr1 = ptr;
1050    if (!ptr1) return;
1051    do 
1052      {
1053        pACB->pDCBRunRobin = ptr1->pNextDCB;
1054        if( !( pSRB = ptr1->pWaitingSRB ) ||
1055            ( ptr1->MaxCommand <= ptr1->GoingSRBCnt ))
1056          ptr1 = ptr1->pNextDCB;
1057        else
1058          {
1059            /* Try to send to the bus */
1060            if( !dc390_StartSCSI(pACB, ptr1, pSRB) )
1061              dc390_Waiting_to_Going (ptr1, pSRB);
1062            else
1063              dc390_waiting_timer (pACB, HZ/5);
1064            break;
1065          }
1066      } while (ptr1 != ptr);
1067    return;
1068}
1069
1070/* Wake up waiting queue */
1071void DC390_waiting_timed_out (unsigned long ptr)
1072{
1073        PACB pACB = (PACB)ptr;
1074        DC390_IFLAGS
1075        DC390_AFLAGS
1076        DEBUG0(printk ("DC390: Debug: Waiting queue woken up by timer!\n");)
1077        DC390_LOCK_IO;
1078        DC390_LOCK_ACB;
1079        dc390_Waiting_process (pACB);
1080        DC390_UNLOCK_ACB;
1081        DC390_UNLOCK_IO;
1082}
1083
1084/***********************************************************************
1085 * Function: static void dc390_SendSRB (PACB pACB, PSRB pSRB)
1086 *
1087 * Purpose: Send SCSI Request Block (pSRB) to adapter (pACB)
1088 *
1089 ***********************************************************************/
1090
1091static void dc390_SendSRB( PACB pACB, PSRB pSRB )
1092{
1093    PDCB   pDCB;
1094
1095    pDCB = pSRB->pSRBDCB;
1096    if( (pDCB->MaxCommand <= pDCB->GoingSRBCnt) || (pACB->pActiveDCB) ||
1097        (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV)) )
1098    {
1099        dc390_Waiting_append (pDCB, pSRB);
1100        dc390_Waiting_process (pACB);
1101        return;
1102    }
1103
1104#if 0
1105    if( pDCB->pWaitingSRB )
1106    {
1107        dc390_Waiting_append (pDCB, pSRB);
1108/*      pSRB = GetWaitingSRB(pDCB); */  /* non-existent */
1109        pSRB = pDCB->pWaitingSRB;
1110        /* Remove from waiting list */
1111        pDCB->pWaitingSRB = pSRB->pNextSRB;
1112        pSRB->pNextSRB = NULL;
1113        if (!pDCB->pWaitingSRB) pDCB->pWaitLast = NULL;
1114    }
1115#endif
1116        
1117    if (!dc390_StartSCSI(pACB, pDCB, pSRB))
1118        dc390_Going_append (pDCB, pSRB);
1119    else {
1120        dc390_Waiting_insert (pDCB, pSRB);
1121        dc390_waiting_timer (pACB, HZ/5);
1122    };
1123}
1124
1125/***********************************************************************
1126 * Function: static void dc390_BuildSRB (Scsi_Cmd *pcmd, PDCB pDCB, 
1127 *                                       PSRB pSRB)
1128 *
1129 * Purpose: Prepare SRB for being sent to Device DCB w/ command *pcmd
1130 *
1131 ***********************************************************************/
1132
1133static void dc390_BuildSRB (Scsi_Cmnd* pcmd, PDCB pDCB, PSRB pSRB)
1134{
1135    pSRB->pSRBDCB = pDCB;
1136    pSRB->pcmd = pcmd;
1137    //pSRB->ScsiCmdLen = pcmd->cmd_len;
1138    //memcpy (pSRB->CmdBlock, pcmd->cmnd, pcmd->cmd_len);
1139    
1140    if( pcmd->use_sg )
1141    {
1142        pSRB->SGcount = (UCHAR) pcmd->use_sg;
1143        pSRB->pSegmentList = (PSGL) pcmd->request_buffer;
1144    }
1145    else if( pcmd->request_buffer )
1146    {
1147        pSRB->SGcount = 1;
1148        pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
1149        pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
1150        pSRB->Segmentx.length = pcmd->request_bufflen;
1151    }
1152    else
1153        pSRB->SGcount = 0;
1154
1155    pSRB->SGIndex = 0;
1156    pSRB->AdaptStatus = 0;
1157    pSRB->TargetStatus = 0;
1158    pSRB->MsgCnt = 0;
1159    if( pDCB->DevType != TYPE_TAPE )
1160        pSRB->RetryCnt = 1;
1161    else
1162        pSRB->RetryCnt = 0;
1163    pSRB->SRBStatus = 0;
1164    pSRB->SRBFlag = 0;
1165    pSRB->SRBState = 0;
1166    pSRB->TotalXferredLen = 0;
1167    pSRB->SGBusAddr = 0;
1168    pSRB->SGToBeXferLen = 0;
1169    pSRB->ScsiPhase = 0;
1170    pSRB->EndMessage = 0;
1171    pSRB->TagNumber = 255;
1172};
1173
1174/* Put cmnd from Query to Waiting list and send next Waiting cmnd */
1175static void dc390_Query_to_Waiting (PACB pACB)
1176{
1177    Scsi_Cmnd *pcmd;
1178    PSRB   pSRB;
1179    PDCB   pDCB;
1180
1181    if( pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) )
1182        return;
1183
1184    while (pACB->QueryCnt)
1185    {
1186        pSRB = dc390_Free_get ( pACB );
1187        if (!pSRB) return;
1188        pcmd = dc390_Query_get ( pACB );
1189        if (!pcmd) { dc390_Free_insert (pACB, pSRB); return; }; /* should not happen */
1190        pDCB = dc390_findDCB (pACB, pcmd->target, pcmd->lun);
1191        if (!pDCB) 
1192        { 
1193                dc390_Free_insert (pACB, pSRB);
1194                printk (KERN_ERR "DC390: Command in queue to non-existing device!\n");
1195                pcmd->result = MK_RES(DRIVER_ERROR,DID_ERROR,0,0);
1196                DC390_UNLOCK_ACB_NI;
1197                pcmd->done (pcmd);
1198                DC390_LOCK_ACB_NI;
1199        };
1200        dc390_BuildSRB (pcmd, pDCB, pSRB);
1201        dc390_Waiting_append ( pDCB, pSRB );
1202    }
1203}
1204
1205/***********************************************************************
1206 * Function : static int DC390_queue_command (Scsi_Cmnd *cmd,
1207 *                                             void (*done)(Scsi_Cmnd *))
1208 *
1209 * Purpose : enqueues a SCSI command
1210 *
1211 * Inputs : cmd - SCSI command, done - callback function called on 
1212 *          completion, with a pointer to the command descriptor.
1213 *
1214 * Returns : (depending on kernel version)
1215 * 2.0.x: always return 0
1216 * 2.1.x: old model: (use_new_eh_code == 0): like 2.0.x
1217 *        TO BE DONE:
1218 *        new model: return 0 if successful
1219 *                   return 1 if command cannot be queued (queue full)
1220 *                   command will be inserted in midlevel queue then ...
1221 *
1222 ***********************************************************************/
1223
1224int DC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *))
1225{
1226    PDCB   pDCB;
1227    PSRB   pSRB;
1228    DC390_AFLAGS
1229    PACB   pACB = (PACB) cmd->host->hostdata;
1230
1231
1232    DEBUG0(/*  if(pACB->scan_devices) */        \
1233        printk(KERN_INFO "DC390: Queue Cmd=%02x,Tgt=%d,LUN=%d (pid=%li)\n",\
1234                cmd->cmnd[0],cmd->target,cmd->lun,cmd->pid);)
1235
1236    DC390_LOCK_ACB;
1237    
1238    /* Assume BAD_TARGET; will be cleared later */
1239    cmd->result = DID_BAD_TARGET << 16;
1240   
1241    /* TODO: Change the policy: Alway accept TEST_UNIT_READY or INQUIRY 
1242     * commands and alloc a DCB for the device if not yet there. DCB will
1243     * be removed in dc390_SRBdone if SEL_TIMEOUT */
1244
1245    if( (pACB->scan_devices == END_SCAN) && (cmd->cmnd[0] != INQUIRY) )
1246        pACB->scan_devices = 0;
1247
1248    else if( (pACB->scan_devices) && (cmd->cmnd[0] == READ_6) )
1249        pACB->scan_devices = 0;
1250
1251    if ( ( cmd->target >= pACB->pScsiHost->max_id ) || 
1252         (cmd->lun >= pACB->pScsiHost->max_lun) )
1253    {
1254/*      printk ("DC390: Ignore target %d lun %d\n",
1255                cmd->target, cmd->lun); */
1256        DC390_UNLOCK_ACB;
1257        //return (1);
1258        done (cmd);
1259        return (0);
1260    }
1261
1262    if( (pACB->scan_devices || cmd->cmnd[0] == TEST_UNIT_READY || cmd->cmnd[0] == INQUIRY) && 
1263       !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) )
1264    {
1265        pACB->scan_devices = 1;
1266
1267        dc390_initDCB( pACB, &pDCB, cmd->target, cmd->lun );
1268        if (!pDCB)
1269          {
1270            printk (KERN_ERR "DC390: kmalloc for DCB failed, target %02x lun %02x\n", 
1271                    cmd->target, cmd->lun);
1272            DC390_UNLOCK_ACB;
1273            printk ("DC390: No DCB in queue_command!\n");
1274#ifdef USE_NEW_EH
1275            return (1);
1276#else
1277            done (cmd);
1278            return (0);
1279#endif
1280          };
1281            
1282    }
1283    else if( !(pACB->scan_devices) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) )
1284    {
1285        printk(KERN_INFO "DC390: Ignore target %02x lun %02x\n",
1286                cmd->target, cmd->lun); 
1287        DC390_UNLOCK_ACB;
1288        //return (1);
1289        done (cmd);
1290        return (0);
1291    }
1292    else
1293    {
1294        pDCB = dc390_findDCB (pACB, cmd->target, cmd->lun);
1295        if (!pDCB)
1296         {  /* should never happen */
1297            printk (KERN_ERR "DC390: no DCB failed, target %02x lun %02x\n", 
1298                    cmd->target, cmd->lun);
1299            DC390_UNLOCK_ACB;
1300            printk ("DC390: No DCB in queuecommand (2)!\n");
1301#ifdef USE_NEW_EH
1302            return (1);
1303#else
1304            done (cmd);
1305            return (0);
1306#endif
1307         };
1308    }
1309
1310    pACB->Cmds++;
1311    cmd->scsi_done = done;
1312    cmd->result = 0;
1313        
1314    dc390_Query_to_Waiting (pACB);
1315
1316    if( pACB->QueryCnt ) /* Unsent commands ? */
1317    {
1318        DEBUG0(printk ("DC390: QueryCnt != 0\n");)
1319        dc390_Query_append ( cmd, pACB );
1320        dc390_Waiting_process (pACB);
1321    }
1322    else if (pDCB->pWaitingSRB)
1323    {
1324        pSRB = dc390_Free_get ( pACB );
1325        DEBUG0(if (!pSRB) printk ("DC390: No free SRB but Waiting\n"); else printk ("DC390: Free SRB w/ Waiting\n");)
1326        if (!pSRB) dc390_Query_append (cmd, pACB);
1327        else 
1328          {
1329            dc390_BuildSRB (cmd, pDCB, pSRB);
1330            dc390_Waiting_append (pDCB, pSRB);
1331          }
1332        dc390_Waiting_process (pACB);
1333    }
1334    else
1335    {
1336        pSRB = dc390_Free_get ( pACB );
1337        DEBUG0(if (!pSRB) printk ("DC390: No free SRB w/o Waiting\n"); else printk ("DC390: Free SRB w/o Waiting\n");)
1338        if (!pSRB)
1339        {
1340            dc390_Query_append (cmd, pACB);
1341            dc390_Waiting_process (pACB);
1342        }
1343        else 
1344        {
1345            dc390_BuildSRB (cmd, pDCB, pSRB);
1346            dc390_SendSRB (pACB, pSRB);
1347        };
1348    };
1349
1350    DC390_UNLOCK_ACB;
1351    DEBUG1(printk (KERN_DEBUG " ... command (pid %li) queued successfully.\n", cmd->pid);)
1352    return(0);
1353}
1354
1355/* We ignore mapping problems, as we expect everybody to respect 
1356 * valid partition tables. Waiting for complaints ;-) */
1357
1358#ifdef CONFIG_SCSI_DC390T_TRADMAP
1359/* 
1360 * The next function, partsize(), is copied from scsicam.c.
1361 *
1362 * This is ugly code duplication, but I didn't find another way to solve it:
1363 * We want to respect the partition table and if it fails, we apply the 
1364 * DC390 BIOS heuristic. Too bad, just calling scsicam_bios_param() doesn't do
1365 * the job, because we don't know, whether the values returned are from
1366 * the part. table or determined by setsize(). Unfortunately the setsize() 
1367 * values differ from the ones chosen by the DC390 BIOS.
1368 *
1369 * Looking forward to seeing suggestions for a better solution! KG, 98/10/14
1370 */
1371#include <asm/unaligned.h>
1372
1373/*
1374 * Function : static int partsize(struct buffer_head *bh, unsigned long 
1375 *     capacity,unsigned int *cyls, unsigned int *hds, unsigned int *secs);
1376 *
1377 * Purpose : to determine the BIOS mapping used to create the partition
1378 *      table, storing the results in *cyls, *hds, and *secs 
1379 *
1380 * Returns : -1 on failure, 0 on success.
1381 *
1382 */
1383
1384static int partsize(struct buffer_head *bh, unsigned long capacity,
1385    unsigned int  *cyls, unsigned int *hds, unsigned int *secs) {
1386    struct partition *p, *largest = NULL;
1387    int i, largest_cyl;
1388    int cyl, ext_cyl, end_head, end_cyl, end_sector;
1389    unsigned int logical_end, physical_end, ext_physical_end;
1390    
1391
1392    if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
1393        for (largest_cyl = -1, p = (struct partition *) 
1394            (0x1BE + bh->b_data), i = 0; i < 4; ++i, ++p) {
1395            if (!p->sys_ind)
1396                continue;
1397            cyl = p->cyl + ((p->sector & 0xc0) << 2);
1398            if (cyl > largest_cyl) {
1399                largest_cyl = cyl;
1400                largest = p;
1401            }
1402        }
1403    }
1404
1405    if (largest) {
1406        end_cyl = largest->end_cyl + ((largest->end_sector & 0xc0) << 2);
1407        end_head = largest->end_head;
1408        end_sector = largest->end_sector & 0x3f;
1409
1410        physical_end =  end_cyl * (end_head + 1) * end_sector +
1411            end_head * end_sector + end_sector;
1412
1413        /* This is the actual _sector_ number at the end */
1414        logical_end = get_unaligned(&largest->start_sect)
1415                        + get_unaligned(&largest->nr_sects);
1416
1417        /* This is for >1023 cylinders */
1418        ext_cyl= (logical_end-(end_head * end_sector + end_sector))
1419                                        /(end_head + 1) / end_sector;
1420        ext_physical_end = ext_cyl * (end_head + 1) * end_sector +
1421            end_head * end_sector + end_sector;
1422
1423        if ((logical_end == physical_end) ||
1424            (end_cyl==1023 && ext_physical_end==logical_end)) {
1425            *secs = end_sector;
1426            *hds = end_head + 1;
1427            *cyls = capacity / ((end_head + 1) * end_sector);
1428            return 0;
1429        }
1430    }
1431    return -1;
1432}
1433
1434/***********************************************************************
1435 * Function:
1436 *   DC390_bios_param
1437 *
1438 * Description:
1439 *   Return the disk geometry for the given SCSI device.
1440 *   Respect the partition table, otherwise try own heuristic
1441 *
1442 * Note:
1443 *   In contrary to other externally callable funcs (DC390_), we don't lock
1444 ***********************************************************************/
1445int DC390_bios_param (Disk *disk, kdev_t devno, int geom[])
1446{
1447    int heads, sectors, cylinders;
1448    PACB pACB = (PACB) disk->device->host->hostdata;
1449    struct buffer_head *bh;
1450    int ret_code = -1;
1451    int size = disk->capacity;
1452
1453    if ((bh = bread(MKDEV(MAJOR(devno), MINOR(devno)&~0xf), 0, block_size(devno))))
1454    {
1455        /* try to infer mapping from partition table */
1456        ret_code = partsize (bh, (unsigned long) size, (unsigned int *) geom + 2,
1457                             (unsigned int *) geom + 0, (unsigned int *) geom + 1);
1458        brelse (bh);
1459    }
1460    if (ret_code == -1)
1461    {
1462        heads = 64;
1463        sectors = 32;
1464        cylinders = size / (heads * sectors);
1465
1466        if ( (pACB->Gmode2 & GREATER_1G) && (cylinders > 1024) )
1467        {
1468                heads = 255;
1469                sectors = 63;
1470                cylinders = size / (heads * sectors);
1471        }
1472
1473        geom[0] = heads;
1474        geom[1] = sectors;
1475        geom[2] = cylinders;
1476    }
1477
1478    return (0);
1479}
1480#else
1481int DC390_bios_param (Disk *disk, kdev_t devno, int geom[])
1482{
1483    return scsicam_bios_param (disk, devno, geom);
1484};
1485#endif
1486
1487
1488void dc390_dumpinfo (PACB pACB, PDCB pDCB, PSRB pSRB)
1489{
1490    USHORT pstat; PDEVDECL1;
1491    if (!pDCB) pDCB = pACB->pActiveDCB;
1492    if (!pSRB && pDCB) pSRB = pDCB->pActiveSRB;
1493
1494    if (pSRB) 
1495    {
1496        printk ("DC390: SRB: Xferred %08lx, Remain %08lx, State %08x, Phase %02x\n",
1497                pSRB->TotalXferredLen, pSRB->SGToBeXferLen, pSRB->SRBState,
1498                pSRB->ScsiPhase);
1499        printk ("DC390: AdpaterStatus: %02x, SRB Status %02x\n", pSRB->AdaptStatus, pSRB->SRBStatus);
1500    };
1501    printk ("DC390: Status of last IRQ (DMA/SC/Int/IRQ): %08x\n", dc390_laststatus);
1502    printk ("DC390: Register dump: SCSI block:\n");
1503    printk ("DC390: XferCnt  Cmd Stat IntS IRQS FFIS Ctl1 Ctl2 Ctl3 Ctl4\n");
1504    printk ("DC390:  %06x   %02x   %02x   %02x",
1505            DC390_read8(CtcReg_Low) + (DC390_read8(CtcReg_Mid) << 8) + (DC390_read8(CtcReg_High) << 16),
1506            DC390_read8(ScsiCmd), DC390_read8(Scsi_Status), DC390_read8(Intern_State));
1507    printk ("   %02x   %02x   %02x   %02x   %02x   %02x\n",
1508            DC390_read8(INT_Status), DC390_read8(Current_Fifo), DC390_read8(CtrlReg1),
1509            DC390_read8(CtrlReg2), DC390_read8(CtrlReg3), DC390_read8(CtrlReg4));
1510    DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
1511    if (DC390_read8(Current_Fifo) & 0x1f)
1512      {
1513        printk ("DC390: FIFO:");
1514        while (DC390_read8(Current_Fifo) & 0x1f) printk (" %02x", DC390_read8(ScsiFifo));
1515        printk ("\n");
1516      };
1517    printk ("DC390: Register dump: DMA engine:\n");
1518    printk ("DC390: Cmd   STrCnt    SBusA    WrkBC    WrkAC Stat SBusCtrl\n");
1519    printk ("DC390:  %02x %08x %08x %08x %08x   %02x %08x\n",
1520            DC390_read8(DMA_Cmd), DC390_read32(DMA_XferCnt), DC390_read32(DMA_XferAddr),
1521            DC390_read32(DMA_Wk_ByteCntr), DC390_read32(DMA_Wk_AddrCntr),
1522            DC390_read8(DMA_Status), DC390_read32(DMA_ScsiBusCtrl));
1523    DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
1524    PDEVSET1; PCI_READ_CONFIG_WORD(PDEV, PCI_STATUS, &pstat);
1525    printk ("DC390: Register dump: PCI Status: %04x\n", pstat);
1526    printk ("DC390: In case of driver trouble read linux/drivers/scsi/README.tmscsim\n");
1527};
1528
1529
1530/***********************************************************************
1531 * Function : int DC390_abort (Scsi_Cmnd *cmd)
1532 *
1533 * Purpose : Abort an errant SCSI command
1534 *
1535 * Inputs : cmd - command to abort
1536 *
1537 * Returns : 0 on success, -1 on failure.
1538 *
1539 * Status: Buggy !
1540 ***********************************************************************/
1541
1542int DC390_abort (Scsi_Cmnd *cmd)
1543{
1544    PDCB  pDCB;
1545    PSRB  pSRB, psrb;
1546    UINT  count, i;
1547    PSCSICMD  pcmd;
1548    int   status;
1549    //ULONG sbac;
1550    DC390_AFLAGS
1551    PACB  pACB = (PACB) cmd->host->hostdata;
1552
1553    DC390_LOCK_ACB;
1554
1555    printk ("DC390: Abort command (pid %li, Device %02i-%02i)\n",
1556            cmd->pid, cmd->target, cmd->lun);
1557
1558    /* First scan Query list */
1559    if( pACB->QueryCnt )
1560    {
1561        pcmd = pACB->pQueryHead;
1562        if( pcmd == cmd )
1563        {
1564            /* Found: Dequeue */
1565            pACB->pQueryHead = pcmd->next;
1566            pcmd->next = NULL;
1567            if (cmd == pACB->pQueryTail) pACB->pQueryTail = NULL;
1568            pACB->QueryCnt--;
1569            status = SCSI_ABORT_SUCCESS;
1570            goto  ABO_X;
1571        }
1572        for( count = pACB->QueryCnt, i=0; i<count-1; i++)
1573        {
1574            if( pcmd->next == cmd )
1575            {
1576                pcmd->next = cmd->next;
1577                cmd->next = NULL;
1578                if (cmd == pACB->pQueryTail) pACB->pQueryTail = NULL;
1579                pACB->QueryCnt--;
1580                status = SCSI_ABORT_SUCCESS;
1581                goto  ABO_X;
1582            }
1583            else
1584            {
1585                pcmd = pcmd->next;
1586            }
1587        }
1588    }
1589        
1590    pDCB = dc390_findDCB (pACB, cmd->target, cmd->lun);
1591    if( !pDCB ) goto  NOT_RUN;
1592
1593    /* Added 98/07/02 KG */
1594    /*
1595    pSRB = pDCB->pActiveSRB;
1596    if (pSRB && pSRB->pcmd == cmd )
1597        goto ON_GOING;
1598     */
1599    
1600    pSRB = pDCB->pWaitingSRB;
1601    if( !pSRB )
1602        goto  ON_GOING;
1603
1604    /* Now scan Waiting queue */
1605    if( pSRB->pcmd == cmd )
1606    {
1607        pDCB->pWaitingSRB = pSRB->pNextSRB;
1608        goto  IN_WAIT;
1609    }
1610    else
1611    {
1612        psrb = pSRB;
1613        if( !(psrb->pNextSRB) )
1614            goto ON_GOING;
1615        while( psrb->pNextSRB->pcmd != cmd )
1616        {
1617            psrb = psrb->pNextSRB;
1618            if( !(psrb->pNextSRB) || psrb == pSRB)
1619                goto ON_GOING;
1620        }
1621        pSRB = psrb->pNextSRB;
1622        psrb->pNextSRB = pSRB->pNextSRB;
1623        if( pSRB == pDCB->pWaitLast )
1624            pDCB->pWaitLast = psrb;
1625IN_WAIT:
1626        dc390_Free_insert (pACB, pSRB);
1627        pDCB->WaitSRBCnt--;
1628        cmd->next = NULL;
1629        status = SCSI_ABORT_SUCCESS;
1630        goto  ABO_X;
1631    }
1632
1633    /* SRB has already been sent ! */
1634ON_GOING:
1635    /* abort() is too stupid for already sent commands at the moment. 
1636     * If it's called we are in trouble anyway, so let's dump some info 
1637     * into the syslog at least. (KG, 98/08/20,99/06/20) */
1638    dc390_dumpinfo (pACB, pDCB, pSRB);
1639    pSRB = pDCB->pGoingSRB;
1640    pDCB->DCBFlag |= ABORT_DEV_;
1641    /* Now for the hard part: The command is currently processed */
1642    for( count = pDCB->GoingSRBCnt, i=0; i<count; i++)
1643    {
1644        if( pSRB->pcmd != cmd )
1645            pSRB = pSRB->pNextSRB;
1646        else
1647        {
1648            if( (pACB->pActiveDCB == pDCB) && (pDCB->pActiveSRB == pSRB) )
1649            {
1650                status = SCSI_ABORT_BUSY;
1651                printk ("DC390: Abort current command (pid %li, SRB %p)\n",
1652                        cmd->pid, pSRB);
1653                goto  ABO_X;
1654            }
1655            else
1656            {
1657                status = SCSI_ABORT_SNOOZE;
1658                goto  ABO_X;
1659            }
1660        }
1661    }
1662
1663NOT_RUN:
1664    status = SCSI_ABORT_NOT_RUNNING;
1665
1666ABO_X:
1667    cmd->result = DID_ABORT << 16;
1668    printk(KERN_INFO "DC390: Aborted pid %li with status %i\n", cmd->pid, status);
1669#if 0
1670    if (cmd->pid == dc390_lastabortedpid) /* repeated failure ? */
1671        {
1672                /* Let's do something to help the bus getting clean again */
1673                DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
1674                DC390_write8 (ScsiCmd, DMA_COMMAND);
1675                //DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1676                //DC390_write8 (ScsiCmd, RESET_ATN_CMD);
1677                DC390_write8 (ScsiCmd, NOP_CMD);
1678                //udelay (10000);
1679                //DC390_read8 (INT_Status);
1680                //DC390_write8 (ScsiCmd, EN_SEL_RESEL);
1681        };
1682    sbac = DC390_read32 (DMA_ScsiBusCtrl);
1683    if (sbac & SCSI_BUSY)
1684    {   /* clear BSY, SEL and ATN */
1685        printk (KERN_WARNING "DC390: Reset SCSI device: ");
1686        //DC390_write32 (DMA_ScsiBusCtrl, (sbac | SCAM) & ~SCSI_LINES);
1687        //udelay (250);
1688        //sbac = DC390_read32 (DMA_ScsiBusCtrl);
1689        //printk ("%08lx ", sbac);
1690        //DC390_write32 (DMA_ScsiBusCtrl, sbac & ~(SCSI_LINES | SCAM));
1691        //udelay (100);
1692        //sbac = DC390_read32 (DMA_ScsiBusCtrl);
1693        //printk ("%08lx ", sbac);
1694        DC390_write8 (ScsiCmd, RST_DEVICE_CMD);
1695        udelay (250);
1696        DC390_write8 (ScsiCmd, NOP_CMD);
1697        sbac = DC390_read32 (DMA_ScsiBusCtrl);
1698        printk ("%08lx\n", sbac);
1699    };
1700#endif
1701    dc390_lastabortedpid = cmd->pid;
1702    DC390_UNLOCK_ACB;
1703    //do_DC390_Interrupt (pACB->IRQLevel, 0, 0);
1704#ifndef USE_NEW_EH      
1705    if (status == SCSI_ABORT_SUCCESS) cmd->scsi_done(cmd);
1706#endif  
1707    return( status );
1708}
1709
1710
1711static void dc390_ResetDevParam( PACB pACB )
1712{
1713    PDCB   pDCB, pdcb;
1714
1715    pDCB = pACB->pLinkDCB;
1716    if (! pDCB) return;
1717    pdcb = pDCB;
1718    do
1719    {
1720        pDCB->SyncMode &= ~SYNC_NEGO_DONE;
1721        pDCB->SyncPeriod = 0;
1722        pDCB->SyncOffset = 0;
1723        pDCB->TagMask = 0;
1724        pDCB->CtrlR3 = FAST_CLK;
1725        pDCB->CtrlR4 &= NEGATE_REQACKDATA | CTRL4_RESERVED | NEGATE_REQACK;
1726        pDCB->CtrlR4 |= pACB->glitch_cfg;
1727        pDCB = pDCB->pNextDCB;
1728    }
1729    while( pdcb != pDCB );
1730    pACB->ACBFlag &= ~(RESET_DEV | RESET_DONE | RESET_DETECT);
1731
1732}
1733
1734#if 0
1735/* Moves all SRBs from Going to Waiting for all DCBs */
1736static void dc390_RecoverSRB( PACB pACB )
1737{
1738    PDCB   pDCB, pdcb;
1739    PSRB   psrb, psrb2;
1740    UINT   cnt, i;
1741
1742    pDCB = pACB->pLinkDCB;
1743    if( !pDCB ) return;
1744    pdcb = pDCB;
1745    do
1746    {
1747        cnt = pdcb->GoingSRBCnt;
1748        psrb = pdcb->pGoingSRB;
1749        for (i=0; i<cnt; i++)
1750        {
1751            psrb2 = psrb;
1752            psrb = psrb->pNextSRB;
1753/*          dc390_RewaitSRB( pDCB, psrb ); */
1754            if( pdcb->pWaitingSRB )
1755            {
1756                psrb2->pNextSRB = pdcb->pWaitingSRB;
1757                pdcb->pWaitingSRB = psrb2;
1758            }
1759            else
1760            {
1761                pdcb->pWaitingSRB = psrb2;
1762                pdcb->pWaitLast = psrb2;
1763                psrb2->pNextSRB = NULL;
1764            }
1765        }
1766        pdcb->GoingSRBCnt = 0;
1767        pdcb->pGoingSRB = NULL;
1768        pdcb->TagMask = 0;
1769        pdcb = pdcb->pNextDCB;
1770    } while( pdcb != pDCB );
1771}
1772#endif
1773
1774/***********************************************************************
1775 * Function : int DC390_reset (Scsi_Cmnd *cmd, ...)
1776 *
1777 * Purpose : perform a hard reset on the SCSI bus
1778 *
1779 * Inputs : cmd - command which caused the SCSI RESET
1780 *          resetFlags - how hard to try
1781 *
1782 * Returns : 0 on success.
1783 ***********************************************************************/
1784
1785int DC390_reset (Scsi_Cmnd *cmd, unsigned int resetFlags)
1786{
1787    UCHAR   bval;
1788    DC390_AFLAGS
1789    PACB    pACB = (PACB) cmd->host->hostdata;
1790
1791    printk(KERN_INFO "DC390: RESET ... ");
1792
1793    DC390_LOCK_ACB;
1794    if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer);
1795    bval = DC390_read8 (CtrlReg1);
1796    bval |= DIS_INT_ON_SCSI_RST;
1797    DC390_write8 (CtrlReg1, bval);      /* disable IRQ on bus reset */
1798
1799    pACB->ACBFlag |= RESET_DEV;
1800    dc390_ResetSCSIBus( pACB );
1801
1802    dc390_ResetDevParam( pACB );
1803    udelay (1000);
1804    pACB->pScsiHost->last_reset = jiffies + 3*HZ/2 
1805                + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
1806    
1807    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1808    DC390_read8 (INT_Status);           /* Reset Pending INT */
1809
1810    dc390_DoingSRB_Done( pACB, cmd );
1811    /* dc390_RecoverSRB (pACB); */
1812    pACB->pActiveDCB = NULL;
1813
1814    pACB->ACBFlag = 0;
1815    bval = DC390_read8 (CtrlReg1);
1816    bval &= ~DIS_INT_ON_SCSI_RST;
1817    DC390_write8 (CtrlReg1, bval);      /* re-enable interrupt */
1818
1819    dc390_Waiting_process( pACB );
1820
1821    printk("done\n");
1822    DC390_UNLOCK_ACB;
1823    return( SCSI_RESET_SUCCESS );
1824}
1825
1826#include "scsiiom.c"
1827
1828
1829/***********************************************************************
1830 * Function : static void dc390_initDCB()
1831 *
1832 * Purpose :  initialize the internal structures for a DCB (to be malloced)
1833 *
1834 * Inputs : SCSI id and lun
1835 ***********************************************************************/
1836
1837void dc390_initDCB( PACB pACB, PDCB *ppDCB, UCHAR id, UCHAR lun )
1838{
1839    PEEprom     prom;
1840    UCHAR       index;
1841    PDCB pDCB, pDCB2;
1842
1843    pDCB = kmalloc (sizeof(DC390_DCB), GFP_ATOMIC);
1844    DCBDEBUG(printk (KERN_INFO "DC390: alloc mem for DCB (ID %i, LUN %i): %p\n" \
1845            id, lun, pDCB);)
1846 
1847    *ppDCB = pDCB; pDCB2 = 0;
1848    if (!pDCB) return;
1849    if( pACB->DCBCnt == 0 )
1850    {
1851        pACB->pLinkDCB = pDCB;
1852        pACB->pDCBRunRobin = pDCB;
1853    }
1854    else
1855    {
1856        pACB->pLastDCB->pNextDCB = pDCB;
1857    };
1858   
1859    pACB->DCBCnt++;
1860   
1861    pDCB->pNextDCB = pACB->pLinkDCB;
1862    pACB->pLastDCB = pDCB;
1863
1864    pDCB->pDCBACB = pACB;
1865    pDCB->TargetID = id;
1866    pDCB->TargetLUN = lun;
1867    pDCB->pWaitingSRB = NULL;
1868    pDCB->pGoingSRB = NULL;
1869    pDCB->GoingSRBCnt = 0;
1870    pDCB->WaitSRBCnt = 0;
1871    pDCB->pActiveSRB = NULL;
1872    pDCB->TagMask = 0;
1873    pDCB->MaxCommand = 1;
1874    index = pACB->AdapterIndex;
1875    pDCB->DCBFlag = 0;
1876
1877    /* Is there a corresp. LUN==0 device ? */
1878    if (lun != 0)
1879        pDCB2 = dc390_findDCB (pACB, id, 0);
1880    prom = (PEEprom) &dc390_eepromBuf[index][id << 2];
1881    /* Some values are for all LUNs: Copy them */
1882    /* In a clean way: We would have an own structure for a SCSI-ID */
1883    if (pDCB2)
1884    {
1885      pDCB->DevMode = pDCB2->DevMode;
1886      pDCB->SyncMode = pDCB2->SyncMode;
1887      pDCB->SyncPeriod = pDCB2->SyncPeriod;
1888      pDCB->SyncOffset = pDCB2->SyncOffset;
1889      pDCB->NegoPeriod = pDCB2->NegoPeriod;
1890      
1891      pDCB->CtrlR3 = pDCB2->CtrlR3;
1892      pDCB->CtrlR4 = pDCB2->CtrlR4;
1893      pDCB->Inquiry7 = pDCB2->Inquiry7;
1894    }
1895    else
1896    {           
1897      pDCB->DevMode = prom->EE_MODE1;
1898      pDCB->SyncMode = 0;
1899      pDCB->SyncPeriod = 0;
1900      pDCB->SyncOffset = 0;
1901      pDCB->NegoPeriod = (dc390_clock_period1[prom->EE_SPEED] * 25) >> 2;
1902            
1903      pDCB->CtrlR3 = FAST_CLK;
1904      
1905      pDCB->CtrlR4 = pACB->glitch_cfg | CTRL4_RESERVED;
1906      if( dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION)
1907        pDCB->CtrlR4 |= NEGATE_REQACKDATA | NEGATE_REQACK;
1908      pDCB->Inquiry7 = 0;
1909    }
1910
1911    pACB->DCBmap[id] |= (1 << lun);
1912    dc390_updateDCB(pACB, pDCB);
1913}
1914
1915/***********************************************************************
1916 * Function : static void dc390_updateDCB()
1917 *
1918 * Purpose :  Set the configuration dependent DCB parameters
1919 ***********************************************************************/
1920
1921void dc390_updateDCB (PACB pACB, PDCB pDCB)
1922{
1923  pDCB->SyncMode &= EN_TAG_QUEUEING | SYNC_NEGO_DONE /*| EN_ATN_STOP*/;
1924  if (pDCB->DevMode & TAG_QUEUEING_) {
1925        //if (pDCB->SyncMode & EN_TAG_QUEUEING) pDCB->MaxCommand = pACB->TagMaxNum;
1926  } else {
1927        pDCB->SyncMode &= ~EN_TAG_QUEUEING;
1928        pDCB->MaxCommand = 1;
1929  };
1930
1931  if( pDCB->DevMode & SYNC_NEGO_ )
1932        pDCB->SyncMode |= SYNC_ENABLE;
1933  else {
1934        pDCB->SyncMode &= ~(SYNC_NEGO_DONE | SYNC_ENABLE);
1935        pDCB->SyncOffset &= ~0x0f;
1936  };
1937
1938  //if (! (pDCB->DevMode & EN_DISCONNECT_)) pDCB->SyncMode &= ~EN_ATN_STOP; 
1939
1940  pDCB->CtrlR1 = pACB->pScsiHost->this_id;
1941  if( pDCB->DevMode & PARITY_CHK_ )
1942        pDCB->CtrlR1 |= PARITY_ERR_REPO;
1943};  
1944
1945
1946/***********************************************************************
1947 * Function : static void dc390_updateDCBs ()
1948 *
1949 * Purpose :  Set the configuration dependent DCB params for all DCBs
1950 ***********************************************************************/
1951
1952static void dc390_updateDCBs (PACB pACB)
1953{
1954  int i;
1955  PDCB pDCB = pACB->pLinkDCB;
1956  for (i = 0; i < pACB->DCBCnt; i++)
1957    {
1958      dc390_updateDCB (pACB, pDCB);
1959      pDCB = pDCB->pNextDCB;
1960    };
1961};
1962  
1963
1964/***********************************************************************
1965 * Function : static void dc390_initSRB()
1966 *
1967 * Purpose :  initialize the internal structures for a given SRB
1968 *
1969 * Inputs : psrb - pointer to this scsi request block structure
1970 ***********************************************************************/
1971
1972static void __inline__ dc390_initSRB( PSRB psrb )
1973{
1974  /* psrb->PhysSRB = virt_to_phys( psrb ); */
1975}
1976
1977
1978void dc390_linkSRB( PACB pACB )
1979{
1980    UINT   count, i;
1981
1982    count = pACB->SRBCount;
1983    for( i=0; i<count; i++)
1984    {
1985        if( i != count-1 )
1986            pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1];
1987        else
1988            pACB->SRB_array[i].pNextSRB = NULL;
1989        dc390_initSRB( &pACB->SRB_array[i] );
1990    }
1991}
1992
1993
1994/***********************************************************************
1995 * Function : static void dc390_initACB ()
1996 *
1997 * Purpose :  initialize the internal structures for a given SCSI host
1998 *
1999 * Inputs : psh - pointer to this host adapter's structure
2000 *          io_port, Irq, index: Resources and adapter index
2001 ***********************************************************************/
2002
2003void __init dc390_initACB (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index)
2004{
2005    PACB    pACB;
2006    UCHAR   i;
2007    DC390_AFLAGS
2008
2009    psh->can_queue = MAX_CMD_QUEUE;
2010    psh->cmd_per_lun = MAX_CMD_PER_LUN;
2011    psh->this_id = (int) dc390_eepromBuf[index][EE_ADAPT_SCSI_ID];
2012    psh->io_port = io_port;
2013    psh->n_io_port = 0x80;
2014    psh->irq = Irq;
2015#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,50)
2016    psh->base = io_port;
2017#else
2018    psh->base = (char*)io_port;
2019#endif  
2020    psh->unique_id = io_port;
2021    psh->dma_channel = -1;
2022    psh->last_reset = jiffies;
2023        
2024    pACB = (PACB) psh->hostdata;
2025    DC390_LOCKA_INIT;
2026    DC390_LOCK_ACB;
2027
2028    pACB->pScsiHost = psh;
2029    pACB->IOPortBase = (USHORT) io_port;
2030    pACB->IRQLevel = Irq;
2031
2032    DEBUG0(printk (KERN_INFO "DC390: Adapter index %i, ID %i, IO 0x%08x, IRQ 0x%02x\n", \
2033            index, psh->this_id, (int)io_port, Irq);)
2034   
2035    psh->max_id = 8;
2036
2037    if( psh->max_id - 1 == dc390_eepromBuf[index][EE_ADAPT_SCSI_ID] )
2038        psh->max_id--;
2039    psh->max_lun = 1;
2040    if( dc390_eepromBuf[index][EE_MODE2] & LUN_CHECK )
2041        psh->max_lun = 8;
2042
2043    pACB->pLinkDCB = NULL;
2044    pACB->pDCBRunRobin = NULL;
2045    pACB->pActiveDCB = NULL;
2046    pACB->pFreeSRB = pACB->SRB_array;
2047    pACB->SRBCount = MAX_SRB_CNT;
2048    pACB->QueryCnt = 0;
2049    pACB->pQueryHead = NULL;
2050    pACB->AdapterIndex = index;
2051    pACB->status = 0;
2052    psh->this_id = dc390_eepromBuf[index][EE_ADAPT_SCSI_ID];
2053    pACB->DeviceCnt = 0;
2054    pACB->DCBCnt = 0;
2055    pACB->TagMaxNum = 2 << dc390_eepromBuf[index][EE_TAG_CMD_NUM];
2056    pACB->ACBFlag = 0;
2057    pACB->scan_devices = 1;
2058    pACB->MsgLen = 0;
2059    pACB->Ignore_IRQ = 0;
2060    pACB->Gmode2 = dc390_eepromBuf[index][EE_MODE2];
2061    dc390_linkSRB( pACB );
2062    pACB->pTmpSRB = &pACB->TmpSRB;
2063    dc390_initSRB( pACB->pTmpSRB );
2064    for(i=0; i<MAX_SCSI_ID; i++)
2065        pACB->DCBmap[i] = 0;
2066    pACB->sel_timeout = SEL_TIMEOUT;
2067    pACB->glitch_cfg = EATER_25NS;
2068    pACB->Cmds = pACB->CmdInQ = pACB->CmdOutOfSRB = 0;
2069    pACB->SelLost = pACB->SelConn = 0;
2070    init_timer (&pACB->Waiting_Timer);
2071}
2072
2073
2074/***********************************************************************
2075 * Function : static int dc390_initAdapter ()
2076 *
2077 * Purpose :  initialize the SCSI chip ctrl registers
2078 *
2079 * Inputs : psh - pointer to this host adapter's structure
2080 *          io_port, Irq, index: Resources
2081 *
2082 * Outputs: 0 on success, -1 on error
2083 ***********************************************************************/
2084
2085int __init dc390_initAdapter (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index)
2086{
2087    PACB   pACB, pACB2;
2088    UCHAR  dstate;
2089    int    i;
2090    
2091    pACB = (PACB) psh->hostdata;
2092    
2093    if (check_region (io_port, psh->n_io_port))
2094        {
2095            printk(KERN_ERR "DC390: register IO ports error!\n");
2096            return( -1 );
2097        }
2098    else
2099        request_region (io_port, psh->n_io_port, "tmscsim");
2100
2101    DC390_read8_ (INT_Status, io_port);         /* Reset Pending INT */
2102
2103    if( (i = request_irq(Irq, do_DC390_Interrupt, DC390_IRQ, "tmscsim", pACB) ))
2104      {
2105        printk(KERN_ERR "DC390: register IRQ error!\n");
2106        release_region (io_port, psh->n_io_port);
2107        return( -1 );
2108      }
2109
2110    if( !dc390_pACB_start )
2111      {
2112        pACB2 = NULL;
2113        dc390_pACB_start = pACB;
2114        dc390_pACB_current = pACB;
2115        pACB->pNextACB = NULL;
2116      }
2117    else
2118      {
2119        pACB2 = dc390_pACB_current;
2120        dc390_pACB_current->pNextACB = pACB;
2121        dc390_pACB_current = pACB;
2122        pACB->pNextACB = NULL;
2123      };
2124
2125    DC390_write8 (CtrlReg1, DIS_INT_ON_SCSI_RST | psh->this_id);        /* Disable SCSI bus reset interrupt */
2126
2127    if (pACB->Gmode2 & RST_SCSI_BUS)
2128    {
2129        dc390_ResetSCSIBus( pACB );
2130        udelay (1000);
2131        pACB->pScsiHost->last_reset = jiffies + HZ/2
2132                    + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
2133        /*
2134        for( i=0; i<(500 + 1000*dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]); i++ )
2135                udelay(1000);
2136         */
2137    };
2138    pACB->ACBFlag = 0;
2139    DC390_read8 (INT_Status);                           /* Reset Pending INT */
2140    
2141    DC390_write8 (Scsi_TimeOut, SEL_TIMEOUT);           /* 250ms selection timeout */
2142    DC390_write8 (Clk_Factor, CLK_FREQ_40MHZ);          /* Conversion factor = 0 , 40MHz clock */
2143    DC390_write8 (ScsiCmd, NOP_CMD);                    /* NOP cmd - clear command register */
2144    DC390_write8 (CtrlReg2, EN_FEATURE+EN_SCSI2_CMD);   /* Enable Feature and SCSI-2 */
2145    DC390_write8 (CtrlReg3, FAST_CLK);                  /* fast clock */
2146    DC390_write8 (CtrlReg4, pACB->glitch_cfg |                  /* glitch eater */
2147                (dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION) ? NEGATE_REQACKDATA : 0);  /* Negation */
2148    DC390_write8 (CtcReg_High, 0);                      /* Clear Transfer Count High: ID */
2149    DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
2150    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
2151    DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
2152    dstate = DC390_read8 (DMA_Status);
2153    DC390_write8 (DMA_Status, dstate);  /* clear */
2154
2155    return(0);
2156}
2157
2158
2159/***********************************************************************
2160 * Function : static int DC390_init (struct Scsi_Host *host, ...)
2161 *
2162 * Purpose :  initialize the internal structures for a given SCSI host
2163 *
2164 * Inputs : host - pointer to this host adapter's structure
2165 *          io_port - IO ports mapped to this adapter
2166 *          Irq - IRQ assigned to this adpater
2167 *          PDEVDECL - PCI access handle
2168 *          index - Adapter index
2169 *
2170 * Outputs: 0 on success, -1 on error
2171 *
2172 * Note: written in capitals, because the locking is only done here,
2173 *      not in DC390_detect, called from outside 
2174 ***********************************************************************/
2175
2176static int __init DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, PDEVDECL, UCHAR index)
2177{
2178    PSH   psh;
2179    PACB  pACB;
2180    DC390_AFLAGS
2181    
2182    if (dc390_CheckEEpromCheckSum (PDEV, index))
2183    {
2184#ifdef CONFIG_SCSI_DC390T_NOGENSUPP
2185        printk (KERN_ERR "DC390_init: No EEPROM found!\n");
2186        return( -1 );
2187#else
2188        int speed;
2189        dc390_adapname = "AM53C974";
2190        printk (KERN_INFO "DC390_init: No EEPROM found! Trying default settings ...\n");
2191        dc390_check_for_safe_settings ();
2192        dc390_fill_with_defaults ();
2193        dc390_EEprom_Override (index);
2194        speed = dc390_clock_speed[tmscsim[1]];
2195        printk (KERN_INFO "DC390: Used defaults: AdaptID=%i, SpeedIdx=%i (%i.%i MHz),"
2196                " DevMode=0x%02x, AdaptMode=0x%02x, TaggedCmnds=%i (%i), DelayReset=%is\n", 
2197                tmscsim[0], tmscsim[1], speed/10, speed%10,
2198                (UCHAR)tmscsim[2], (UCHAR)tmscsim[3], tmscsim[4], 2 << (tmscsim[4]), tmscsim[5]);
2199#endif
2200    }
2201    else
2202    {
2203        dc390_check_for_safe_settings ();
2204        dc390_EEprom_Override (index);
2205    }
2206   
2207    psh = scsi_register( psht, sizeof(DC390_ACB) );
2208    if( !psh ) return( -1 );
2209        
2210    scsi_set_pci_device(psh, pdev);
2211    pACB = (PACB) psh->hostdata;
2212    DC390_LOCKA_INIT;
2213    DC390_LOCK_ACB;
2214
2215#if 0
2216    if( !dc390_pSH_start )
2217    {
2218        dc390_pSH_start = psh;
2219        dc390_pSH_current = psh;
2220    }
2221    else
2222    {
2223        dc390_pSH_current->next = psh;
2224        dc390_pSH_current = psh;
2225    }
2226#endif
2227
2228    DEBUG0(printk(KERN_INFO "DC390: pSH = %8x,", (UINT) psh);)
2229    DEBUG0(printk(" Index %02i,", index);)
2230
2231    dc390_initACB( psh, io_port, Irq, index );
2232    pACB = (PACB) psh->hostdata;
2233        
2234    PDEVSET;
2235
2236    if( !dc390_initAdapter( psh, io_port, Irq, index ) )
2237    {
2238        DEBUG0(printk("\nDC390: pACB = %8x, pDCBmap = %8x, pSRB_array = %8x\n",\
2239                (UINT) pACB, (UINT) pACB->DCBmap, (UINT) pACB->SRB_array);)
2240        DEBUG0(printk("DC390: ACB size= %4x, DCB size= %4x, SRB size= %4x\n",\
2241                sizeof(DC390_ACB), sizeof(DC390_DCB), sizeof(DC390_SRB) );)
2242
2243        DC390_UNLOCK_ACB;
2244        return (0);
2245    }
2246    else
2247    {
2248        //dc390_pSH_start = NULL;
2249        scsi_unregister( psh );
2250        DC390_UNLOCK_ACB;
2251        return( -1 );
2252    }
2253}
2254
2255
2256/***********************************************************************
2257 * Function : int DC390_detect(Scsi_Host_Template *psht)
2258 *
2259 * Purpose : detects and initializes AMD53C974 SCSI chips
2260 *           that were autoprobed, overridden on the LILO command line,
2261 *           or specified at compile time.
2262 *
2263 * Inputs : psht - template for this SCSI adapter
2264 *
2265 * Returns : number of host adapters detected
2266 *
2267 ***********************************************************************/
2268
2269#ifndef NEW_PCI
2270/* Acc. to PCI 2.1 spec it's up to the driver to enable Bus mastering:
2271 * We use pci_set_master () for 2.1.x and this func for 2.0.x:  */
2272static void __init dc390_set_master (PDEVDECL)
2273{
2274        USHORT cmd;
2275        UCHAR lat;
2276        
2277        PCI_READ_CONFIG_WORD (PDEV, PCI_COMMAND, &cmd);
2278        
2279        if (! (cmd & PCI_COMMAND_MASTER)) {     
2280                printk("PCI: Enabling bus mastering for device %02x:%02x\n",
2281                       PCI_BUS_DEV);
2282                cmd |= PCI_COMMAND_MASTER;
2283                PCI_WRITE_CONFIG_WORD(PDEV, PCI_COMMAND, cmd);
2284        }
2285        PCI_READ_CONFIG_BYTE (PDEV, PCI_LATENCY_TIMER, &lat);
2286        if (lat < 16 /* || lat == 255 */) {
2287                printk("PCI: Setting latency timer of device %02x:%02x from %i to 64\n",
2288                       PCI_BUS_DEV, lat);
2289                PCI_WRITE_CONFIG_BYTE(PDEV, PCI_LATENCY_TIMER, 64);
2290        }
2291        
2292};
2293#endif /* ! NEW_PCI */
2294
2295static void __init dc390_set_pci_cfg (PDEVDECL)
2296{
2297        USHORT cmd;
2298        PCI_READ_CONFIG_WORD (PDEV, PCI_COMMAND, &cmd);
2299        cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_IO;
2300        PCI_WRITE_CONFIG_WORD (PDEV, PCI_COMMAND, cmd);
2301        PCI_WRITE_CONFIG_WORD (PDEV, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY));
2302};
2303        
2304
2305int __init DC390_detect (Scsi_Host_Template *psht)
2306{
2307    PDEVDECL0;
2308    UCHAR   irq;
2309    UINT    io_port;
2310    //DC390_IFLAGS
2311    DC390_DFLAGS
2312
2313    DC390_LOCK_DRV;
2314    //dc390_pSHT_start = psht;
2315    dc390_pACB_start = NULL;
2316
2317    if ( PCI_PRESENT )
2318        while (PCI_FIND_DEVICE (PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974))
2319        {
2320#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,30)
2321            if (pci_enable_device (pdev))
2322                continue;
2323#endif
2324            //DC390_LOCK_IO;            /* Remove this when going to new eh */
2325            PCI_GET_IO_AND_IRQ;
2326            DEBUG0(printk(KERN_INFO "DC390(%i): IO_PORT=%04x,IRQ=%x\n", dc390_adapterCnt, (UINT) io_port, irq);)
2327
2328            if( !DC390_init(psht, io_port, irq, PDEV, dc390_adapterCnt))
2329            {
2330                PCI_SET_MASTER;
2331                dc390_set_pci_cfg (PDEV);
2332                dc390_adapterCnt++;
2333            };
2334            //DC390_UNLOCK_IO;          /* Remove when going to new eh */
2335        }
2336    else
2337        printk (KERN_ERR "DC390: No PCI BIOS found!\n");
2338   
2339    if (dc390_adapterCnt)
2340#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30)
2341        psht->proc_name = "tmscsim";
2342#else
2343        psht->proc_dir = &DC390_proc_scsi_tmscsim;
2344#endif
2345    printk(KERN_INFO "DC390: %i adapters found\n", dc390_adapterCnt);
2346    DC390_UNLOCK_DRV;
2347    return( dc390_adapterCnt );
2348}
2349
2350
2351/***********************************************************************
2352 * Functions: dc390_inquiry(), dc390_inquiry_done()
2353 *
2354 * Purpose: When changing speed etc., we have to issue an INQUIRY
2355 *          command to make sure, we agree upon the nego parameters
2356 *          with the device
2357 ***********************************************************************/
2358
2359static void dc390_inquiry_done (Scsi_Cmnd* cmd)
2360{
2361   printk (KERN_INFO "DC390: INQUIRY (ID %02x LUN %02x) returned %08x\n",
2362           cmd->target, cmd->lun, cmd->result);
2363   if (cmd->result)
2364   {
2365        PACB pACB = (PACB)cmd->host->hostdata;
2366        PDCB pDCB = dc390_findDCB (pACB, cmd->target, cmd->lun);
2367        printk ("DC390: Unsetting DsCn, Sync and TagQ!\n");
2368        if (pDCB)
2369        {
2370                pDCB->DevMode &= ~(SYNC_NEGO_ | TAG_QUEUEING_ | EN_DISCONNECT_ );
2371                dc390_updateDCB (pACB, pDCB);
2372        };
2373   };
2374   kfree (cmd);
2375};
2376
2377void dc390_inquiry (PACB pACB, PDCB pDCB)
2378{
2379   char* buffer;
2380   Scsi_Cmnd* cmd;
2381   cmd = kmalloc (sizeof(Scsi_Cmnd) + 256, GFP_ATOMIC);
2382   if (!cmd) { printk ("DC390: kmalloc failed in inquiry!\n"); return; };
2383   buffer = (char*)cmd + sizeof(Scsi_Cmnd);
2384
2385   memset (cmd, 0, sizeof(Scsi_Cmnd) + 256);
2386   cmd->cmnd[0] = INQUIRY;
2387   cmd->cmnd[1] = (pDCB->TargetLUN << 5) & 0xe0;
2388   cmd->cmnd[4] = 0xff;
2389   
2390   cmd->cmd_len = 6; cmd->old_cmd_len = 6;
2391   cmd->host = pACB->pScsiHost;
2392   cmd->target = pDCB->TargetID;
2393   cmd->lun = pDCB->TargetLUN; 
2394   cmd->serial_number = 1;
2395   cmd->pid = 390;
2396   cmd->bufflen = 128;
2397   cmd->buffer = buffer;
2398   cmd->request_bufflen = 128;
2399   cmd->request_buffer = &buffer[128];
2400   cmd->done = dc390_inquiry_done;
2401   cmd->scsi_done = dc390_inquiry_done;
2402   cmd->timeout_per_command = HZ;
2403
2404   cmd->request.rq_status = RQ_SCSI_BUSY;
2405
2406   pDCB->SyncMode &= ~SYNC_NEGO_DONE;
2407   printk (KERN_INFO "DC390: Queue INQUIRY command to dev ID %02x LUN %02x\n",
2408           pDCB->TargetID, pDCB->TargetLUN);
2409   DC390_queue_command (cmd, dc390_inquiry_done);
2410};
2411
2412/***********************************************************************
2413 * Functions: dc390_sendstart(), dc390_sendstart_done()
2414 *
2415 * Purpose: When changing speed etc., we have to issue an INQUIRY
2416 *          command to make sure, we agree upon the nego parameters
2417 *          with the device
2418 ***********************************************************************/
2419
2420static void dc390_sendstart_done (Scsi_Cmnd* cmd)
2421{
2422   printk (KERN_INFO "DC390: SENDSTART (ID %02x LUN %02x) returned %08x\n",
2423           cmd->target, cmd->lun, cmd->result);
2424   kfree (cmd);
2425};
2426
2427void dc390_sendstart (PACB pACB, PDCB pDCB)
2428{
2429   char* buffer;
2430   Scsi_Cmnd* cmd;
2431   cmd = kmalloc (sizeof(Scsi_Cmnd) + 256, GFP_ATOMIC);
2432   if (!cmd) { printk ("DC390: kmalloc failed in sendstart!\n"); return; };
2433   buffer = (char*)cmd + sizeof(Scsi_Cmnd);
2434
2435   memset (cmd, 0, sizeof(Scsi_Cmnd) + 256);
2436   cmd->cmnd[0] = 0x1b; /* START_STOP_UNIT */
2437   cmd->cmnd[1] = (pDCB->TargetLUN << 5) & 0xe0;
2438   cmd->cmnd[4] = 0x01; /* START */
2439   
2440   cmd->cmd_len = 6; cmd->old_cmd_len = 6;
2441   cmd->host = pACB->pScsiHost;
2442   cmd->target = pDCB->TargetID;
2443   cmd->lun = pDCB->TargetLUN; 
2444   cmd->serial_number = 1;
2445   cmd->pid = 310;
2446   cmd->bufflen = 128;
2447   cmd->buffer = buffer;
2448   cmd->request_bufflen = 128;
2449   cmd->request_buffer = &buffer[128];
2450   cmd->done = dc390_sendstart_done;
2451   cmd->scsi_done = dc390_sendstart_done;
2452   cmd->timeout_per_command = 5*HZ;
2453
2454   cmd->request.rq_status = RQ_SCSI_BUSY;
2455
2456   pDCB->SyncMode &= ~SYNC_NEGO_DONE;
2457   printk (KERN_INFO "DC390: Queue SEND_START command to dev ID %02x LUN %02x\n",
2458           pDCB->TargetID, pDCB->TargetLUN);
2459   DC390_queue_command (cmd, dc390_sendstart_done);
2460};
2461
2462/********************************************************************
2463 * Function: dc390_set_info()
2464 *
2465 * Purpose: Change adapter config
2466 *
2467 * Strings are parsed similar to the output of tmscsim_proc_info ()
2468 * '-' means no change
2469 *******************************************************************/
2470
2471static int dc390_scanf (char** p1, char** p2, int* var)
2472{
2473   *p2 = *p1;
2474   *var = simple_strtoul (*p2, p1, 10);
2475   if (*p2 == *p1) return -1;
2476   *p1 = strtok (0, " \t\n:=,;.");
2477   return 0;
2478};
2479
2480#define SCANF(p1, p2, var, min, max)            \
2481if (dc390_scanf (&p1, &p2, &var)) goto einv;    \
2482else if (var<min || var>max) goto einv2
2483
2484static int dc390_yesno (char** p, char* var, char bmask)
2485{
2486   switch (**p)
2487     {
2488      case 'Y': *var |= bmask; break;
2489      case 'N': *var &= ~bmask; break;
2490      case '-': break;
2491      default: return -1;
2492     }
2493   *p = strtok (0, " \t\n:=,;");
2494   return 0;
2495};
2496
2497#define YESNO(p, var, bmask)                    \
2498if (dc390_yesno (&p, &var, bmask)) goto einv;   \
2499else dc390_updateDCB (pACB, pDCB);              \
2500if (!p) goto ok
2501
2502static int dc390_search (char **p1, char **p2, char *var, char* txt, int max, int scale, char* ign)
2503{
2504   int dum;
2505   if (! memcmp (*p1, txt, strlen(txt)))
2506     {
2507        *p2 = strtok (0, " \t\n:=,;");
2508        if (!*p2) return -1;
2509        dum = simple_strtoul (*p2, p1, 10);
2510        if (*p2 == *p1) return -1;
2511        if (dum >= 0 && dum <= max) 
2512          { *var = (dum * 100) / scale; }
2513        else return -2;
2514        *p1 = strtok (0, " \t\n:=,;");
2515        if (*ign && *p1 && strlen(*p1) >= strlen(ign) && 
2516            !(memcmp (*p1, ign, strlen(ign)))) 
2517                *p1 = strtok (0, " \t\n:=,;");
2518
2519     }
2520   return 0;
2521};
2522
2523#define SEARCH(p1, p2, var, txt, max)                                           \
2524if (dc390_search (&p1, &p2, (PUCHAR)(&var), txt, max, 100, "")) goto einv2;     \
2525else if (!p1) goto ok2
2526
2527#define SEARCH2(p1, p2, var, txt, max, scale)                                   \
2528if (dc390_search (&p1, &p2, &var, txt, max, scale, "")) goto einv2;             \
2529else if (!p1) goto ok2
2530
2531#define SEARCH3(p1, p2, var, txt, max, scale, ign)                              \
2532if (dc390_search (&p1, &p2, &var, txt, max, scale, ign)) goto einv2;            \
2533else if (!p1) goto ok2
2534
2535
2536#ifdef DC390_PARSEDEBUG
2537static char _prstr[256];
2538char* prstr (char* p, char* e)
2539{
2540   char* c = _prstr;
2541   while (p < e)
2542     if (*p == 0) { *c++ = ':'; p++; }
2543     else if (*p == 10) { *c++ = '\\'; *c++ = 'n'; p++; }
2544     else *c++ = *p++;
2545   *c = 0;
2546   return _prstr;
2547};
2548#endif
2549
2550int dc390_set_info (char *buffer, int length, PACB pACB)
2551{
2552  char *pos = buffer, *p0 = buffer;
2553  char needs_inquiry = 0; 
2554  int dum = 0;
2555  char dev;
2556  PDCB pDCB = pACB->pLinkDCB;
2557  DC390_IFLAGS
2558  DC390_AFLAGS 
2559  pos[length] = 0;
2560
2561  DC390_LOCK_IO;
2562  DC390_LOCK_ACB;
2563  /* UPPERCASE */ 
2564  /* Don't use kernel toupper, because of 2.0.x bug: ctmp unexported */
2565  while (*pos) 
2566    { if (*pos >='a' && *pos <= 'z') *pos = *pos + 'A' - 'a'; pos++; };
2567  
2568  /* We should protect __strtok ! */
2569  /* spin_lock (strtok_lock); */
2570
2571  /* Remove WS */
2572  pos = strtok (buffer, " \t:\n=,;");
2573  if (!pos) goto ok;
2574   
2575 next:
2576  if (!memcmp (pos, "RESET", 5)) goto reset;
2577  else if (!memcmp (pos, "INQUIRY", 7)) goto inquiry;
2578  else if (!memcmp (pos, "REMOVE", 6)) goto remove;
2579  else if (!memcmp (pos, "ADD", 3)) goto add;
2580  else if (!memcmp (pos, "START", 5)) goto start;
2581  else if (!memcmp (pos, "DUMP", 4)) goto dump;
2582  
2583  if (isdigit (*pos))
2584    {
2585      /* Device config line */
2586      int dev, id, lun; char* pdec;
2587      char olddevmode;
2588      
2589      SCANF (pos, p0, dev, 0, pACB->DCBCnt-1);
2590      if (pos) { SCANF (pos, p0, id, 0, 7); } else goto einv;
2591      if (pos) { SCANF (pos, p0, lun, 0, 7); } else goto einv;
2592      if (!pos) goto einv;
2593      
2594      PARSEDEBUG(printk (KERN_INFO "DC390: config line %i %i %i:\"%s\"\n", dev, id, lun, prstr (pos, &buffer[length]));)
2595      pDCB = pACB->pLinkDCB;
2596      for (dum = 0; dum < dev; dum++) pDCB = pDCB->pNextDCB;
2597      /* Sanity Check */
2598      if (pDCB->TargetID != id || pDCB->TargetLUN != lun) 
2599         {
2600            printk (KERN_ERR "DC390: no such device: Idx=%02i ID=%02i LUN=%02i\n",
2601                    dev, id, lun);
2602            goto einv2;
2603         };
2604
2605      if (pDCB->pWaitingSRB || pDCB->pGoingSRB)
2606      {
2607          printk ("DC390: Cannot change dev (%i-%i) cfg: Pending requests\n",
2608                  pDCB->TargetID, pDCB->TargetLUN);
2609          goto einv;
2610      };
2611          
2612      olddevmode = pDCB->DevMode;
2613      YESNO (pos, pDCB->DevMode, PARITY_CHK_);
2614      needs_inquiry++;
2615      YESNO (pos, pDCB->DevMode, SYNC_NEGO_);
2616      if ((olddevmode & SYNC_NEGO_) == (pDCB->DevMode & SYNC_NEGO_)) needs_inquiry--;
2617      needs_inquiry++;
2618      YESNO (pos, pDCB->DevMode, EN_DISCONNECT_);
2619      if ((olddevmode & EN_DISCONNECT_) == (pDCB->DevMode & EN_DISCONNECT_)) needs_inquiry--;
2620      YESNO (pos, pDCB->DevMode, SEND_START_);
2621      needs_inquiry++;
2622      YESNO (pos, pDCB->DevMode, TAG_QUEUEING_);
2623      if ((olddevmode & TAG_QUEUEING_) == (pDCB->DevMode & TAG_QUEUEING_)) needs_inquiry--;
2624
2625      dc390_updateDCB (pACB, pDCB);
2626      if (!pos) goto ok;
2627       
2628      olddevmode = pDCB->NegoPeriod;
2629      /* Look for decimal point (Speed) */
2630      pdec = pos; 
2631      while (pdec++ < &buffer[length]) if (*pdec == '.') break;
2632      /* NegoPeriod */
2633      if (*pos != '-')
2634        {
2635          SCANF (pos, p0, dum, 72, 800); 
2636          pDCB->NegoPeriod = dum >> 2;
2637          if (pDCB->NegoPeriod != olddevmode) needs_inquiry++;
2638          if (!pos) goto ok;
2639          if (memcmp (pos, "NS", 2) == 0) pos = strtok (0, " \t\n:=,;.");
2640        }
2641      else pos = strtok (0, " \t\n:=,;.");
2642      if (!pos) goto ok;
2643      
2644      /* Sync Speed in MHz */
2645      if (*pos != '-')
2646        {
2647          SCANF (pos, p0, dum, 1, 13); 
2648          pDCB->NegoPeriod = (1000/dum) >> 2;
2649          if (pDCB->NegoPeriod != olddevmode && !pos) needs_inquiry++;
2650          if (!pos) goto ok;
2651          /* decimal */
2652          if (pos-1 == pdec)
2653             {
2654                int dumold = dum;
2655                dum = simple_strtoul (pos, &p0, 10) * 10;
2656                for (; p0-pos > 1; p0--) dum /= 10;
2657                pDCB->NegoPeriod = (100000/(100*dumold + dum)) >> 2;
2658                if (pDCB->NegoPeriod < 19) pDCB->NegoPeriod = 19;
2659                pos = strtok (0, " \t\n:=,;");
2660                if (!pos) goto ok;
2661             };
2662          if (*pos == 'M') pos = strtok (0, " \t\n:=,;");
2663          if (pDCB->NegoPeriod != olddevmode) needs_inquiry++;
2664        }
2665      else pos = strtok (0, " \t\n:=,;");
2666      /* dc390_updateDCB (pACB, pDCB); */
2667      if (!pos) goto ok;
2668
2669      olddevmode = pDCB->SyncOffset;
2670      /* SyncOffs */
2671      if (*pos != '-')
2672        {
2673          SCANF (pos, p0, dum, 0, 0x0f); 
2674          pDCB->SyncOffset = dum;
2675          if (pDCB->SyncOffset > olddevmode) needs_inquiry++;
2676        }
2677      else pos = strtok (0, " \t\n:=,;");
2678      if (!pos) goto ok;
2679      dc390_updateDCB (pACB, pDCB);
2680
2681      //olddevmode = pDCB->MaxCommand;
2682      /* MaxCommand (Tags) */
2683      if (*pos != '-')
2684        {
2685          SCANF (pos, p0, dum, 1, 32 /*pACB->TagMaxNum*/);
2686          if (pDCB->SyncMode & EN_TAG_QUEUEING)
2687                pDCB->MaxCommand = dum;
2688          else printk (KERN_INFO "DC390: Can't set MaxCmd larger than one without Tag Queueing!\n");
2689        }
2690      else pos = strtok (0, " \t\n:=,;");
2691
2692    }
2693  else
2694    {
2695      char* p1 = pos; UCHAR dum, newadaptid;
2696      PARSEDEBUG(printk (KERN_INFO "DC390: chg adapt cfg \"%s\"\n", prstr (pos, &buffer[length]));)
2697      dum = GLITCH_TO_NS (pACB->glitch_cfg);
2698      /* Adapter setting */
2699      SEARCH (pos, p0, pACB->pScsiHost->max_id, "MAXID", 8); 
2700      SEARCH (pos, p0, pACB->pScsiHost->max_lun, "MAXLUN", 8); 
2701      SEARCH (pos, p0, newadaptid, "ADAPTERID", 7);
2702      SEARCH (pos, p0, pACB->TagMaxNum, "TAGMAXNUM", 32);
2703      SEARCH (pos, p0, pACB->ACBFlag, "ACBFLAG", 255);
2704      SEARCH3 (pos, p0, dum, "GLITCHEATER", 40, 1000, "NS");
2705      SEARCH3 (pos, p0, pACB->sel_timeout, "SELTIMEOUT", 400, 163, "MS");
2706      SEARCH3 (pos, p0, dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY], "DELAYRESET", 180, 100, "S");
2707    ok2:
2708      pACB->glitch_cfg = NS_TO_GLITCH (dum);
2709      if (pACB->sel_timeout < 60) pACB->sel_timeout = 60;
2710      DC390_write8 (Scsi_TimeOut, pACB->sel_timeout);
2711      if (newadaptid != pACB->pScsiHost->this_id)
2712      {
2713        pACB->pScsiHost->this_id = newadaptid;
2714        dc390_ResetDevParam (pACB);
2715      }     
2716      //dum = 0; while (1 << dum <= pACB->TagMaxNum) dum ++;
2717      //pACB->TagMaxNum &= (1 << --dum);
2718      dc390_updateDCBs (pACB);
2719      // All devs should be INQUIRED now
2720      if (pos == p1) goto einv;
2721    }
2722  if (pos) goto next;
2723      
2724 ok:
2725  /* spin_unlock (strtok_lock); */
2726  DC390_UNLOCK_ACB;
2727  if (needs_inquiry) 
2728     { dc390_updateDCB (pACB, pDCB); dc390_inquiry (pACB, pDCB); };
2729  DC390_UNLOCK_IO;
2730  return (length);
2731
2732 einv2:
2733  pos = p0;
2734 einv:
2735  /* spin_unlock (strtok_lock); */
2736  DC390_UNLOCK_ACB;
2737  DC390_UNLOCK_IO;
2738  printk (KERN_WARNING "DC390: parse error near \"%s\"\n", (pos? pos: "NULL"));
2739  return (-EINVAL);
2740   
2741 reset:
2742     {
2743        Scsi_Cmnd cmd; cmd.host = pACB->pScsiHost;
2744        printk (KERN_WARNING "DC390: Driver reset requested!\n");
2745        DC390_UNLOCK_ACB;
2746        DC390_reset (&cmd, 0);
2747        DC390_UNLOCK_IO;
2748     };
2749  return (length);
2750
2751 dump:
2752     {
2753        dc390_dumpinfo (pACB, 0, 0);
2754        DC390_UNLOCK_ACB;
2755        DC390_UNLOCK_IO;       
2756     }
2757  return (length);
2758        
2759 inquiry:
2760     {
2761        pos = strtok (0, " \t\n.:;="); if (!pos) goto einv;
2762        dev = simple_strtoul (pos, &p0, 10);
2763        if (dev >= pACB->DCBCnt) goto einv_dev;
2764        for (dum = 0; dum < dev; dum++) pDCB = pDCB->pNextDCB;
2765        printk (KERN_NOTICE " DC390: Issue INQUIRY command to Dev(Idx) %i SCSI ID %i LUN %i\n",
2766                dev, pDCB->TargetID, pDCB->TargetLUN);
2767        DC390_UNLOCK_ACB;
2768        dc390_inquiry (pACB, pDCB);
2769        DC390_UNLOCK_IO;
2770     };
2771   return (length);
2772
2773 remove:
2774     {
2775        pos = strtok (0, " \t\n.:;="); if (!pos) goto einv;
2776        dev = simple_strtoul (pos, &p0, 10);
2777        if (dev >= pACB->DCBCnt) goto einv_dev;
2778        for (dum = 0; dum < dev; dum++) pDCB = pDCB->pNextDCB;
2779        printk (KERN_NOTICE " DC390: Remove DCB for Dev(Idx) %i SCSI ID %i LUN %i\n",
2780                dev, pDCB->TargetID, pDCB->TargetLUN);
2781        /* TO DO: We should make sure no pending commands are left */
2782        dc390_remove_dev (pACB, pDCB);
2783        DC390_UNLOCK_ACB;
2784        DC390_UNLOCK_IO;
2785     };
2786   return (length);
2787
2788 add:
2789     {
2790        int id, lun;
2791        pos = strtok (0, " \t\n.:;=");
2792        if (pos) { SCANF (pos, p0, id, 0, 7); } else goto einv;
2793        if (pos) { SCANF (pos, p0, lun, 0, 7); } else goto einv;
2794        pDCB = dc390_findDCB (pACB, id, lun);
2795        if (pDCB) { printk ("DC390: ADD: Device already existing\n"); goto einv; };
2796        dc390_initDCB (pACB, &pDCB, id, lun);
2797        DC390_UNLOCK_ACB;
2798        dc390_inquiry (pACB, pDCB);
2799        DC390_UNLOCK_IO;
2800     };
2801   return (length);
2802
2803 start:
2804     {
2805        int id, lun;
2806        pos = strtok (0, " \t\n.:;=");
2807        if (pos) { SCANF (pos, p0, id, 0, 7); } else goto einv;
2808        if (pos) { SCANF (pos, p0, lun, 0, 7); } else goto einv;
2809        pDCB = dc390_findDCB (pACB, id, lun);
2810        if (pDCB) printk ("DC390: SendStart: Device already existing ...\n");
2811        else dc390_initDCB (pACB, &pDCB, id, lun);
2812        DC390_UNLOCK_ACB;
2813        dc390_sendstart (pACB, pDCB);
2814        dc390_inquiry (pACB, pDCB);
2815        DC390_UNLOCK_IO;
2816     };
2817   return (length);
2818
2819 einv_dev:
2820   printk (KERN_WARNING "DC390: Ignore cmnd to illegal Dev(Idx) %i. Valid range: 0 - %i.\n", 
2821           dev, pACB->DCBCnt - 1);
2822   DC390_UNLOCK_ACB;
2823   DC390_UNLOCK_IO;
2824   return (-EINVAL);
2825             
2826             
2827}
2828
2829#undef SEARCH
2830#undef YESNO
2831#undef SCANF
2832
2833/********************************************************************
2834 * Function: DC390_proc_info(char* buffer, char **start,
2835 *                           off_t offset, int length, int hostno, int inout)
2836 *
2837 * Purpose: return SCSI Adapter/Device Info
2838 *
2839 * Input: buffer: Pointer to a buffer where to write info
2840 *        start :
2841 *        offset:
2842 *        hostno: Host adapter index
2843 *        inout : Read (=0) or set(!=0) info
2844 *
2845 * Output: buffer: contains info
2846 *         length; length of info in buffer
2847 *
2848 * return value: length
2849 *
2850 ********************************************************************/
2851
2852#undef SPRINTF
2853#define SPRINTF(args...) pos += sprintf(pos, ## args)
2854
2855#define YESNO(YN)               \
2856 if (YN) SPRINTF(" Yes ");      \
2857 else SPRINTF(" No  ")
2858
2859
2860int DC390_proc_info (char *buffer, char **start,
2861                     off_t offset, int length, int hostno, int inout)
2862{
2863  int dev, spd, spd1;
2864  char *pos = buffer;
2865  PSH shpnt = 0;
2866  PACB pACB;
2867  PDCB pDCB;
2868  PSCSICMD pcmd;
2869  DC390_AFLAGS
2870
2871  pACB = dc390_pACB_start;
2872
2873  while(pACB != (PACB)-1)
2874     {
2875        shpnt = pACB->pScsiHost;
2876        if (shpnt->host_no == hostno) break;
2877        pACB = pACB->pNextACB;
2878     }
2879
2880  if (pACB == (PACB)-1) return(-ESRCH);
2881  if(!shpnt) return(-ESRCH);
2882
2883  if(inout) /* Has data been written to the file ? */
2884      return dc390_set_info(buffer, length, pACB);
2885   
2886  SPRINTF("Tekram DC390/AM53C974 PCI SCSI Host Adapter, ");
2887  SPRINTF("Driver Version %s\n", DC390_VERSION);
2888
2889  DC390_LOCK_ACB;
2890
2891  SPRINTF("SCSI Host Nr %i, ", shpnt->host_no);
2892  SPRINTF("%s Adapter Nr %i\n", dc390_adapname, pACB->AdapterIndex);
2893  SPRINTF("IOPortBase 0x%04x, ", pACB->IOPortBase);
2894  SPRINTF("IRQ %02i\n", pACB->IRQLevel);
2895
2896  SPRINTF("MaxID %i, MaxLUN %i, ", shpnt->max_id, shpnt->max_lun);
2897  SPRINTF("AdapterID %i, SelTimeout %i ms, DelayReset %i s\n", 
2898          shpnt->this_id, (pACB->sel_timeout*164)/100,
2899          dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]);
2900
2901  SPRINTF("TagMaxNum %i, Status 0x%02x, ACBFlag 0x%02x, GlitchEater %i ns\n",
2902          pACB->TagMaxNum, pACB->status, pACB->ACBFlag, GLITCH_TO_NS(pACB->glitch_cfg)*12);
2903
2904  SPRINTF("Statistics: Cmnds %li, Cmnds not sent directly %i, Out of SRB conds %i\n",
2905          pACB->Cmds, pACB->CmdInQ, pACB->CmdOutOfSRB);
2906  SPRINTF("            Lost arbitrations %i, Sel. connected %i, Connected: %s\n", 
2907          pACB->SelLost, pACB->SelConn, pACB->Connected? "Yes": "No");
2908   
2909  SPRINTF("Nr of attached devices: %i, Nr of DCBs: %i\n", pACB->DeviceCnt, pACB->DCBCnt);
2910  SPRINTF("Map of attached LUNs: %02x %02x %02x %02x %02x %02x %02x %02x\n",
2911          pACB->DCBmap[0], pACB->DCBmap[1], pACB->DCBmap[2], pACB->DCBmap[3], 
2912          pACB->DCBmap[4], pACB->DCBmap[5], pACB->DCBmap[6], pACB->DCBmap[7]);
2913
2914  SPRINTF("Idx ID LUN Prty Sync DsCn SndS TagQ NegoPeriod SyncSpeed SyncOffs MaxCmd\n");
2915
2916  pDCB = pACB->pLinkDCB;
2917  for (dev = 0; dev < pACB->DCBCnt; dev++)
2918     {
2919      SPRINTF("%02i  %02i  %02i ", dev, pDCB->TargetID, pDCB->TargetLUN);
2920      YESNO(pDCB->DevMode & PARITY_CHK_);
2921      YESNO(pDCB->SyncMode & SYNC_NEGO_DONE);
2922      YESNO(pDCB->DevMode & EN_DISCONNECT_);
2923      YESNO(pDCB->DevMode & SEND_START_);
2924      YESNO(pDCB->SyncMode & EN_TAG_QUEUEING);
2925      if (pDCB->SyncOffset & 0x0f)
2926      {
2927         int sp = pDCB->SyncPeriod; if (! (pDCB->CtrlR3 & FAST_SCSI)) sp++;
2928         SPRINTF("  %03i ns ", (pDCB->NegoPeriod) << 2);
2929         spd = 40/(sp); spd1 = 40%(sp);
2930         spd1 = (spd1 * 10 + sp/2) / (sp);
2931         SPRINTF("   %2i.%1i M      %02i", spd, spd1, (pDCB->SyncOffset & 0x0f));
2932      }
2933      else SPRINTF(" (%03i ns)                 ", (pDCB->NegoPeriod) << 2);
2934      /* Add more info ...*/
2935      SPRINTF ("      %02i\n", pDCB->MaxCommand);
2936      pDCB = pDCB->pNextDCB;
2937     }
2938    SPRINTF ("Commands in Queues: Query: %li:", pACB->QueryCnt);
2939    for (pcmd = pACB->pQueryHead; pcmd; pcmd = pcmd->next)
2940        SPRINTF (" %li", pcmd->pid);
2941    if (timer_pending(&pACB->Waiting_Timer)) SPRINTF ("Waiting queue timer running\n");
2942    else SPRINTF ("\n");
2943    pDCB = pACB->pLinkDCB;
2944        
2945    for (dev = 0; dev < pACB->DCBCnt; dev++)
2946    {
2947        PSRB pSRB;
2948        if (pDCB->WaitSRBCnt) 
2949                    SPRINTF ("DCB (%02i-%i): Waiting: %i:", pDCB->TargetID, pDCB->TargetLUN,
2950                             pDCB->WaitSRBCnt);
2951        for (pSRB = pDCB->pWaitingSRB; pSRB; pSRB = pSRB->pNextSRB)
2952                SPRINTF(" %li", pSRB->pcmd->pid);
2953        if (pDCB->GoingSRBCnt) 
2954                    SPRINTF ("\nDCB (%02i-%i): Going  : %i:", pDCB->TargetID, pDCB->TargetLUN,
2955                             pDCB->GoingSRBCnt);
2956        for (pSRB = pDCB->pGoingSRB; pSRB; pSRB = pSRB->pNextSRB)
2957#if 0 //def DC390_DEBUGTRACE
2958                SPRINTF(" %s\n  ", pSRB->debugtrace);
2959#else
2960                SPRINTF(" %li", pSRB->pcmd->pid);
2961#endif
2962        if (pDCB->WaitSRBCnt || pDCB->GoingSRBCnt) SPRINTF ("\n");
2963        pDCB = pDCB->pNextDCB;
2964    }
2965        
2966#ifdef DC390_DEBUGDCB
2967    SPRINTF ("DCB list for ACB %p:\n", pACB);
2968    pDCB = pACB->pLinkDCB;
2969    SPRINTF ("%p", pDCB);
2970    for (dev = 0; dev < pACB->DCBCnt; dev++, pDCB=pDCB->pNextDCB)
2971        SPRINTF ("->%p", pDCB->pNextDCB);
2972    SPRINTF("\n");
2973#endif
2974  
2975
2976  DC390_UNLOCK_ACB;
2977  *start = buffer + offset;
2978
2979  if (pos - buffer < offset)
2980    return 0;
2981  else if (pos - buffer - offset < length)
2982    return pos - buffer - offset;
2983  else
2984    return length;
2985}
2986
2987#undef YESNO
2988#undef SPRINTF
2989
2990#ifdef MODULE
2991
2992/***********************************************************************
2993 * Function : static int dc390_shutdown (struct Scsi_Host *host)
2994 *
2995 * Purpose : does a clean (we hope) shutdown of the SCSI chip.
2996 *           Use prior to dumping core, unloading the driver, etc.
2997 *
2998 * Returns : 0 on success
2999 ***********************************************************************/
3000static int dc390_shutdown (struct Scsi_Host *host)
3001{
3002    UCHAR    bval;
3003    PACB pACB = (PACB)(host->hostdata);
3004   
3005/*  pACB->soft_reset(host); */
3006
3007    printk(KERN_INFO "DC390: shutdown\n");
3008
3009    pACB->ACBFlag = RESET_DEV;
3010    bval = DC390_read8 (CtrlReg1);
3011    bval |= DIS_INT_ON_SCSI_RST;
3012    DC390_write8 (CtrlReg1, bval);      /* disable interrupt */
3013    if (pACB->Gmode2 & RST_SCSI_BUS)
3014                dc390_ResetSCSIBus (pACB);
3015
3016    if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer);
3017    return( 0 );
3018}
3019
3020void dc390_freeDCBs (struct Scsi_Host *host)
3021{
3022    PDCB pDCB, nDCB;
3023    PACB pACB = (PACB)(host->hostdata);
3024    
3025    pDCB = pACB->pLinkDCB;
3026    if (!pDCB) return;
3027    do
3028    {
3029        nDCB = pDCB->pNextDCB;
3030        DCBDEBUG(printk (KERN_INFO "DC390: Free DCB (ID %i, LUN %i): %p\n",\
3031                pDCB->TargetID, pDCB->TargetLUN, pDCB);)
3032        //kfree (pDCB);
3033        dc390_remove_dev (pACB, pDCB);
3034        pDCB = nDCB;
3035    } while (pDCB && pACB->pLinkDCB);
3036
3037};
3038
3039int DC390_release (struct Scsi_Host *host)
3040{
3041    DC390_AFLAGS DC390_IFLAGS
3042    PACB pACB = (PACB)(host->hostdata);
3043
3044    DC390_LOCK_IO;
3045    DC390_LOCK_ACB;
3046
3047    /* TO DO: We should check for outstanding commands first. */
3048    dc390_shutdown (host);
3049
3050    if (host->irq != IRQ_NONE)
3051    {
3052        DEBUG0(printk(KERN_INFO "DC390: Free IRQ %i\n",host->irq);)
3053        free_irq (host->irq, pACB);
3054    }
3055
3056    release_region(host->io_port,host->n_io_port);
3057    dc390_freeDCBs (host);
3058    DC390_UNLOCK_ACB;
3059    DC390_UNLOCK_IO;
3060    return( 1 );
3061}
3062#endif /* def MODULE */
3063
3064#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,99)
3065static Scsi_Host_Template driver_template = DC390_T;
3066#include "scsi_module.c"
3067#endif
3068
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.