OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [scsi/] [tmscsim.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/***********************************************************************
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 1.1.1.1 2004-04-15 02:10:55 phoenix 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)
280
static 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
};
289
MODULE_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
 
436
UCHAR dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB );
437
void dc390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
438
void dc390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
439
static void dc390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
440
static void dc390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
441
static void dc390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
442
void dc390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
443
static void dc390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
444
static void dc390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
445
void dc390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
446
static void dc390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
447
void dc390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
448
static void dc390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
449
static void dc390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
450
static void dc390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus);
451
 
452
static void dc390_SetXferRate( PACB pACB, PDCB pDCB );
453
void dc390_Disconnect( PACB pACB );
454
void dc390_Reselect( PACB pACB );
455
void dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB );
456
void dc390_DoingSRB_Done( PACB pACB, PSCSICMD cmd );
457
static void dc390_ScsiRstDetect( PACB pACB );
458
static void dc390_ResetSCSIBus( PACB pACB );
459
static void __inline__ dc390_RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB );
460
static void __inline__ dc390_InvalidCmd( PACB pACB );
461
static void __inline__ dc390_EnableMsgOut_Abort (PACB, PSRB);
462
static void dc390_remove_dev (PACB pACB, PDCB pDCB);
463
void do_DC390_Interrupt( int, void *, struct pt_regs *);
464
 
465
int    dc390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, UCHAR index );
466
void   dc390_initDCB( PACB pACB, PDCB *ppDCB, UCHAR id, UCHAR lun);
467
void   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;
478
static PACB     dc390_pACB_start= NULL;
479
static PACB     dc390_pACB_current = NULL;
480
static ULONG    dc390_lastabortedpid = 0;
481
static UINT     dc390_laststatus = 0;
482
static UCHAR    dc390_adapterCnt = 0;
483
 
484
/* Startup values, to be overriden on the commandline */
485
int tmscsim[] = {-2, -2, -2, -2, -2, -2};
486
 
487
# if defined(MODULE) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30)
488
MODULE_PARM(tmscsim, "1-6i");
489
MODULE_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)
493
MODULE_AUTHOR("C.L. Huang / Kurt Garloff");
494
MODULE_DESCRIPTION("SCSI host adapter driver for Tekram DC390 and other AMD53C974A based PCI SCSI adapters");
495
MODULE_LICENSE("GPL");
496
 
497
MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
498
#endif
499
 
500
static 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
 
512
static 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
525
static 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
 
537
static 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 */
551
UCHAR  dc390_baddevname1[2][28] ={
552
       "SEAGATE ST3390N         9546",
553
       "HP      C3323-300       4269"};
554
#define BADDEVCNT       2
555
 
556
static char*  dc390_adapname = "DC390";
557
UCHAR  dc390_eepromBuf[MAX_ADAPTER_NUM][EE_LEN];
558
UCHAR  dc390_clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20};
559
UCHAR  dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20};
560
 
561
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,30)
562
struct 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
 
575
static 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 */
592
static 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 */
619
static 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
632
int __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 */
643
static 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)
665
int __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
686
void __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
 
703
static 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
 
724
static 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
 
740
static 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
 
757
static 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
 
773
static 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
 
789
static 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
 
795
static 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
 **********************************************************************/
819
static 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 */
854
static 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 */
869
static 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 */
885
static 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 */
901
static __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 */
917
static __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 */
926
static __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 */
938
static __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
 
952
static __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
 
967
static __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 */
987
static 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 */
998
static __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
 
1018
void DC390_waiting_timed_out (unsigned long ptr);
1019
/* Sets the timer to wake us up */
1020
static 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 */
1035
static 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 */
1071
void 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
 
1091
static 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
 
1133
static 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 */
1175
static 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
 
1224
int 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
 
1384
static 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
 ***********************************************************************/
1445
int 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
1481
int DC390_bios_param (Disk *disk, kdev_t devno, int geom[])
1482
{
1483
    return scsicam_bios_param (disk, devno, geom);
1484
};
1485
#endif
1486
 
1487
 
1488
void 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
 
1542
int 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;
1625
IN_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 ! */
1634
ON_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
 
1663
NOT_RUN:
1664
    status = SCSI_ABORT_NOT_RUNNING;
1665
 
1666
ABO_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
 
1711
static 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 */
1736
static 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
 
1785
int 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
 
1837
void 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
 
1921
void 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
 
1952
static 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
 
1972
static void __inline__ dc390_initSRB( PSRB psrb )
1973
{
1974
  /* psrb->PhysSRB = virt_to_phys( psrb ); */
1975
}
1976
 
1977
 
1978
void 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
 
2003
void __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
 
2085
int __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
 
2176
static 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:  */
2272
static 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
 
2295
static 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
 
2305
int __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
 
2359
static 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
 
2377
void 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
 
2420
static 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
 
2427
void 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
 
2471
static 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)            \
2481
if (dc390_scanf (&p1, &p2, &var)) goto einv;    \
2482
else if (var<min || var>max) goto einv2
2483
 
2484
static 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)                    \
2498
if (dc390_yesno (&p, &var, bmask)) goto einv;   \
2499
else dc390_updateDCB (pACB, pDCB);              \
2500
if (!p) goto ok
2501
 
2502
static 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)                                           \
2524
if (dc390_search (&p1, &p2, (PUCHAR)(&var), txt, max, 100, "")) goto einv2;     \
2525
else if (!p1) goto ok2
2526
 
2527
#define SEARCH2(p1, p2, var, txt, max, scale)                                   \
2528
if (dc390_search (&p1, &p2, &var, txt, max, scale, "")) goto einv2;             \
2529
else if (!p1) goto ok2
2530
 
2531
#define SEARCH3(p1, p2, var, txt, max, scale, ign)                              \
2532
if (dc390_search (&p1, &p2, &var, txt, max, scale, ign)) goto einv2;            \
2533
else if (!p1) goto ok2
2534
 
2535
 
2536
#ifdef DC390_PARSEDEBUG
2537
static char _prstr[256];
2538
char* 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
 
2550
int 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
 
2860
int 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
 ***********************************************************************/
3000
static 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
 
3020
void 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
 
3039
int 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 != SCSI_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)
3065
static Scsi_Host_Template driver_template = DC390_T;
3066
#include "scsi_module.c"
3067
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.