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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [scsi/] [tmscsim.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/***********************************************************************
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                            *
9
*************************************************************************/
10
/* $Id: tmscsim.c,v 1.1 2005-12-20 10:17:45 jcastillo Exp $             */
11
/*      Enhancements and bugfixes by                                    *
12
 *      Kurt Garloff <kurt@garloff.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
 *                              competely reworked. Handle target ini-  *
99
 *                              tiated SDTR correctly.                  *
100
 ***********************************************************************/
101
 
102
/* Uncomment SA_INTERRUPT, if the driver refuses to share its IRQ with other devices */
103
#define DC390_IRQ SA_SHIRQ /* | SA_INTERRUPT */
104
 
105
/* DEBUG options */
106
//#define DC390_DEBUG0
107
//#define DC390_DEBUG1
108
//#define DC390_DCBDEBUG
109
//#define DC390_PARSEDEBUG
110
//#define DC390_REMOVABLEDEBUG
111
 
112
/* Debug definitions */
113
#ifdef DC390_DEBUG0
114
# define DEBUG0(x) x;
115
#else
116
# define DEBUG0(x)
117
#endif
118
#ifdef DC390_DEBUG1
119
# define DEBUG1(x) x;
120
#else
121
# define DEBUG1(x)
122
#endif
123
#ifdef DC390_DCBDEBUG
124
# define DCBDEBUG(x) x;
125
#else
126
# define DCBDEBUG(x)
127
#endif
128
#ifdef DC390_PARSEDEBUG
129
# define PARSEDEBUG(x) x;
130
#else
131
# define PARSEDEBUG(x)
132
#endif
133
#ifdef DC390_REMOVABLEDEBUG
134
# define REMOVABLEDEBUG(x) x;
135
#else
136
# define REMOVABLEDEBUG(x)
137
#endif
138
#define DCBDEBUG1(x)
139
 
140
/* Includes */
141
#ifdef MODULE
142
# include <linux/module.h>
143
#endif
144
 
145
#include <asm/dma.h>
146
#include <asm/io.h>
147
#include <asm/system.h>
148
#include <linux/delay.h>
149
#include <linux/signal.h>
150
#include <linux/sched.h>
151
#include <linux/errno.h>
152
#include <linux/kernel.h>
153
#include <linux/ioport.h>
154
#include <linux/pci.h>
155
#include <linux/proc_fs.h>
156
#include <linux/string.h>
157
#include <linux/ctype.h>
158
#include <linux/mm.h>
159
#include <linux/config.h>
160
#include <linux/version.h>
161
#include <linux/blk.h>
162
 
163
#include "scsi.h"
164
#include "hosts.h"
165
#include "constants.h"
166
#include "sd.h"
167
#include <linux/stat.h>
168
 
169
#include "dc390.h"
170
 
171
#define PCI_DEVICE_ID_AMD53C974         PCI_DEVICE_ID_AMD_SCSI
172
 
173
/* Locking */
174
 
175
/* Note: Starting from 2.1.9x, the mid-level scsi code issues a
176
 * spinlock_irqsave (&io_request_lock) before calling the driver's
177
 * routines, so we don't need to lock.
178
 * TODO: Verify, if we are locked in every case!
179
 * The policy 3, let the midlevel scsi code do the io_request_locks
180
 * and us locking on a driver specific lock, shouldn't hurt anybody; it
181
 * just causes a minor performance degradation for setting the locks.
182
 */
183
 
184
/* spinlock things
185
 * level 3: lock on both adapter specific locks and (global) io_request_lock
186
 * level 2: lock on adapter specific locks only
187
 * level 1: rely on the locking of the mid level code (io_request_lock)
188
 * undef  : traditional save_flags; cli; restore_flags;
189
 */
190
 
191
//#define DEBUG_SPINLOCKS 2     /* Set to 0, 1 or 2 in include/asm/spinlock.h */
192
 
193
#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
194
 
195
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30)
196
# include <linux/init.h>
197
# include <asm/spinlock.h>
198
#endif
199
 
200
 
201
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93) 
202
# define USE_SPINLOCKS 1
203
# define NEW_PCI 1
204
#else
205
# undef NEW_PCI
206
# if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30)
207
#  define USE_SPINLOCKS 2
208
# endif
209
#endif
210
 
211
#ifdef USE_SPINLOCKS
212
 
213
# if USE_SPINLOCKS == 3 /* both */
214
 
215
#  if defined (__SMP__) || DEBUG_SPINLOCKS > 0
216
#   define DC390_LOCKA_INIT { spinlock_t __unlocked = SPIN_LOCK_UNLOCKED; pACB->lock = __unlocked; };
217
#  else
218
#   define DC390_LOCKA_INIT
219
#  endif
220
   spinlock_t dc390_drvlock = SPIN_LOCK_UNLOCKED;
221
 
222
#  define DC390_AFLAGS unsigned long aflags;
223
#  define DC390_IFLAGS unsigned long iflags;
224
#  define DC390_DFLAGS unsigned long dflags; 
225
 
226
#  define DC390_LOCK_IO spin_lock_irqsave (&io_request_lock, iflags)
227
#  define DC390_UNLOCK_IO spin_unlock_irqrestore (&io_request_lock, iflags)
228
 
229
#  define DC390_LOCK_DRV spin_lock_irqsave (&dc390_drvlock, dflags)
230
#  define DC390_UNLOCK_DRV spin_unlock_irqrestore (&dc390_drvlock, dflags)
231
#  define DC390_LOCK_DRV_NI spin_lock (&dc390_drvlock)
232
#  define DC390_UNLOCK_DRV_NI spin_unlock (&dc390_drvlock)
233
 
234
#  define DC390_LOCK_ACB spin_lock_irqsave (&(pACB->lock), aflags)
235
#  define DC390_UNLOCK_ACB spin_unlock_irqrestore (&(pACB->lock), aflags)
236
#  define DC390_LOCK_ACB_NI spin_lock (&(pACB->lock))
237
#  define DC390_UNLOCK_ACB_NI spin_unlock (&(pACB->lock))
238
//#  define DC390_LOCKA_INIT spin_lock_init (&(pACB->lock))
239
 
240
# else
241
 
242
#  if USE_SPINLOCKS == 2 /* adapter specific locks */
243
 
244
#   if defined (__SMP__) || DEBUG_SPINLOCKS > 0
245
#    define DC390_LOCKA_INIT { spinlock_t __unlocked = SPIN_LOCK_UNLOCKED; pACB->lock = __unlocked; };
246
#   else
247
#    define DC390_LOCKA_INIT
248
#   endif
249
    spinlock_t dc390_drvlock = SPIN_LOCK_UNLOCKED;
250
#   define DC390_AFLAGS unsigned long aflags;
251
#   define DC390_IFLAGS 
252
#  define DC390_DFLAGS unsigned long dflags; 
253
#   define DC390_LOCK_IO /* spin_lock_irqsave (&io_request_lock, iflags) */
254
#   define DC390_UNLOCK_IO /* spin_unlock_irqrestore (&io_request_lock, iflags) */
255
#   define DC390_LOCK_DRV spin_lock_irqsave (&dc390_drvlock, dflags)
256
#   define DC390_UNLOCK_DRV spin_unlock_irqrestore (&dc390_drvlock, dflags)
257
#   define DC390_LOCK_DRV_NI spin_lock (&dc390_drvlock)
258
#   define DC390_UNLOCK_DRV_NI spin_unlock (&dc390_drvlock)
259
#   define DC390_LOCK_ACB spin_lock_irqsave (&(pACB->lock), aflags)
260
#   define DC390_UNLOCK_ACB spin_unlock_irqrestore (&(pACB->lock), aflags)
261
#   define DC390_LOCK_ACB_NI spin_lock (&(pACB->lock))
262
#   define DC390_UNLOCK_ACB_NI spin_unlock (&(pACB->lock))
263
//#   define DC390_LOCKA_INIT spin_lock_init (&(pACB->lock))
264
 
265
#  else /* USE_SPINLOCKS == 1: global lock io_request_lock */
266
 
267
#   define DC390_AFLAGS 
268
#   define DC390_IFLAGS unsigned long iflags;
269
#   define DC390_DFLAGS unsigned long dflags; 
270
    spinlock_t dc390_drvlock = SPIN_LOCK_UNLOCKED;
271
#   define DC390_LOCK_IO spin_lock_irqsave (&io_request_lock, iflags)
272
#   define DC390_UNLOCK_IO spin_unlock_irqrestore (&io_request_lock, iflags)
273
#   define DC390_LOCK_DRV spin_lock_irqsave (&dc390_drvlock, dflags)
274
#   define DC390_UNLOCK_DRV spin_unlock_irqrestore (&dc390_drvlock, dflags)
275
#   define DC390_LOCK_DRV_NI spin_lock (&dc390_drvlock)
276
#   define DC390_UNLOCK_DRV_NI spin_unlock (&dc390_drvlock)
277
#   define DC390_LOCK_ACB /* DC390_LOCK_IO */
278
#   define DC390_UNLOCK_ACB /* DC390_UNLOCK_IO */
279
#   define DC390_LOCK_ACB_NI /* spin_lock (&(pACB->lock)) */
280
#   define DC390_UNLOCK_ACB_NI /* spin_unlock (&(pACB->lock)) */
281
#   define DC390_LOCKA_INIT /* DC390_LOCKA_INIT */
282
 
283
#  endif /* 2 */
284
# endif /* 3 */
285
 
286
#else /* USE_SPINLOCKS undefined */
287
 
288
# define DC390_AFLAGS unsigned long aflags;
289
# define DC390_IFLAGS unsigned long iflags;
290
# define DC390_DFLAGS unsigned long dflags; 
291
# define DC390_LOCK_IO save_flags (iflags); cli ()
292
# define DC390_UNLOCK_IO restore_flags (iflags)
293
# define DC390_LOCK_DRV save_flags (dflags); cli ()
294
# define DC390_UNLOCK_DRV restore_flags (dflags)
295
# define DC390_LOCK_DRV_NI
296
# define DC390_UNLOCK_DRV_NI
297
# define DC390_LOCK_ACB save_flags (aflags); cli ()
298
# define DC390_UNLOCK_ACB restore_flags (aflags)
299
# define DC390_LOCK_ACB_NI
300
# define DC390_UNLOCK_ACB_NI
301
# define DC390_LOCKA_INIT
302
#endif /* def */
303
 
304
 
305
/* These macros are used for uniform access to 2.0.x and 2.1.x PCI config space*/
306
 
307
#ifdef NEW_PCI
308
# define PDEV pdev
309
# define PDEVDECL struct pci_dev *pdev
310
# define PDEVDECL0 struct pci_dev *pdev = NULL
311
# define PDEVDECL1 struct pci_dev *pdev
312
# define PDEVSET pACB->pdev=pdev
313
# define PDEVSET1 pdev=pACB->pdev
314
# define PCI_WRITE_CONFIG_BYTE(pd, rv, bv) pci_write_config_byte (pd, rv, bv)
315
# define PCI_READ_CONFIG_BYTE(pd, rv, bv) pci_read_config_byte (pd, rv, bv)
316
# define PCI_WRITE_CONFIG_WORD(pd, rv, bv) pci_write_config_word (pd, rv, bv)
317
# define PCI_READ_CONFIG_WORD(pd, rv, bv) pci_read_config_word (pd, rv, bv)
318
# define PCI_BUS_DEV pdev->bus->number, pdev->devfn
319
# define PCI_PRESENT pci_present ()
320
# define PCI_SET_MASTER pci_set_master (pdev)
321
# define PCI_FIND_DEVICE(vend, id) (pdev = pci_find_device (vend, id, pdev))
322
# define PCI_GET_IO_AND_IRQ io_port = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; irq = pdev->irq
323
#else
324
# include <linux/bios32.h>
325
# define PDEV pbus, pdevfn
326
# define PDEVDECL UCHAR pbus, UCHAR pdevfn
327
# define PDEVDECL0 UCHAR pbus = 0; UCHAR pdevfn = 0; USHORT pci_index = 0; int error
328
# define PDEVDECL1 UCHAR pbus; UCHAR pdevfn /*; USHORT pci_index */
329
# define PDEVSET pACB->pbus=pbus; pACB->pdevfn=pdevfn /*; pACB->pci_index=pci_index */
330
# define PDEVSET1 pbus=pACB->pbus; pdevfn=pACB->pdevfn /*; pci_index=pACB->pci_index */
331
# define PCI_WRITE_CONFIG_BYTE(pd, rv, bv) pcibios_write_config_byte (pd, rv, bv)
332
# define PCI_READ_CONFIG_BYTE(pd, rv, bv) pcibios_read_config_byte (pd, rv, bv)
333
# define PCI_WRITE_CONFIG_WORD(pd, rv, bv) pcibios_write_config_word (pd, rv, bv)
334
# define PCI_READ_CONFIG_WORD(pd, rv, bv) pcibios_read_config_word (pd, rv, bv)
335
# define PCI_BUS_DEV pbus, pdevfn
336
# define PCI_PRESENT pcibios_present ()
337
# define PCI_SET_MASTER dc390_set_master (pbus, pdevfn)
338
# define PCI_FIND_DEVICE(vend, id) (!pcibios_find_device (vend, id, pci_index++, &pbus, &pdevfn))
339
# define PCI_GET_IO_AND_IRQ error = pcibios_read_config_dword (pbus, pdevfn, PCI_BASE_ADDRESS_0, &io_port);     \
340
 error |= pcibios_read_config_byte (pbus, pdevfn, PCI_INTERRUPT_LINE, &irq);    \
341
 io_port &= 0xfffe;     \
342
 if (error) { printk (KERN_ERR "DC390_detect: Error reading PCI config registers!\n"); continue; }
343
#endif 
344
 
345
#include "tmscsim.h"
346
 
347
#ifndef __init
348
# define __init
349
#endif
350
 
351
UCHAR dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB );
352
void dc390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
353
void dc390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
354
static void dc390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
355
static void dc390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
356
static void dc390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
357
void dc390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
358
static void dc390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
359
static void dc390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
360
void dc390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
361
static void dc390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
362
void dc390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
363
static void dc390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
364
static void dc390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
365
static void dc390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus);
366
 
367
static void dc390_SetXferRate( PACB pACB, PDCB pDCB );
368
void dc390_Disconnect( PACB pACB );
369
void dc390_Reselect( PACB pACB );
370
void dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB );
371
void dc390_DoingSRB_Done( PACB pACB );
372
static void dc390_ScsiRstDetect( PACB pACB );
373
static void dc390_ResetSCSIBus( PACB pACB );
374
static void __inline__ dc390_RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB );
375
static void __inline__ dc390_InvalidCmd( PACB pACB );
376
static void __inline__ dc390_EnableMsgOut_Abort (PACB, PSRB);
377
static void dc390_remove_dev (PACB pACB, PDCB pDCB);
378
void do_DC390_Interrupt( int, void *, struct pt_regs *);
379
 
380
int    dc390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, UCHAR index );
381
void   dc390_initDCB( PACB pACB, PDCB *ppDCB, PSCSICMD cmd );
382
void   dc390_updateDCB (PACB pACB, PDCB pDCB);
383
 
384
#ifdef MODULE
385
 static int DC390_release(struct Scsi_Host *host);
386
 static int dc390_shutdown (struct Scsi_Host *host);
387
#endif
388
 
389
 
390
//static PSHT   dc390_pSHT_start = NULL;
391
//static PSH    dc390_pSH_start = NULL;
392
//static PSH    dc390_pSH_current = NULL;
393
static PACB     dc390_pACB_start= NULL;
394
static PACB     dc390_pACB_current = NULL;
395
static UCHAR    dc390_adapterCnt = 0;
396
static UCHAR    dc390_CurrSyncOffset = 0;
397
static ULONG    dc390_lastabortedpid = 0;
398
static ULONG    dc390_laststatus = 0;
399
 
400
#ifndef CONFIG_SCSI_DC390T_NOGENSUPP
401
/* Startup values, to be overriden on the commandline */
402
int tmscsim[] = {7, 1 /* 8MHz */,
403
                PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_
404
                | SYNC_NEGO_ | TAG_QUEUEING_,
405
                MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION
406
                /* | NO_SEEK */
407
# ifdef CONFIG_SCSI_MULTI_LUN
408
                | LUN_CHECK
409
# endif
410
                , 3 /* 16 Tags per LUN */};
411
 
412
# if defined(MODULE) && LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30)
413
MODULE_PARM(tmscsim, "1-5i");
414
MODULE_PARM_DESC(tmscsim, "Host SCSI ID, Speed (0=10MHz), Device Flags, Adapter Flags, Max Tags (log2(tags)-1)");
415
# endif
416
 
417
#endif /* CONFIG_SCSI_DC390T_NOGENSUPP */
418
 
419
#if defined(MODULE) && LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30)
420
MODULE_AUTHOR("C.L. Huang / Kurt Garloff");
421
MODULE_DESCRIPTION("SCSI host adapter driver for Tekram DC390 and other AMD53C974A based PCI SCSI adapters");
422
MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
423
#endif
424
 
425
static PVOID dc390_phase0[]={
426
       dc390_DataOut_0,
427
       dc390_DataIn_0,
428
       dc390_Command_0,
429
       dc390_Status_0,
430
       dc390_Nop_0,
431
       dc390_Nop_0,
432
       dc390_MsgOut_0,
433
       dc390_MsgIn_0,
434
       dc390_Nop_1
435
       };
436
 
437
static PVOID dc390_phase1[]={
438
       dc390_DataOutPhase,
439
       dc390_DataInPhase,
440
       dc390_CommandPhase,
441
       dc390_StatusPhase,
442
       dc390_Nop_0,
443
       dc390_Nop_0,
444
       dc390_MsgOutPhase,
445
       dc390_MsgInPhase,
446
       dc390_Nop_1
447
       };
448
 
449
#ifdef DC390_DEBUG1
450
static char* dc390_p0_str[] = {
451
       "dc390_DataOut_0",
452
       "dc390_DataIn_0",
453
       "dc390_Command_0",
454
       "dc390_Status_0",
455
       "dc390_Nop_0",
456
       "dc390_Nop_0",
457
       "dc390_MsgOut_0",
458
       "dc390_MsgIn_0",
459
       "dc390_Nop_1"
460
       };
461
 
462
static char* dc390_p1_str[] = {
463
       "dc390_DataOutPhase",
464
       "dc390_DataInPhase",
465
       "dc390_CommandPhase",
466
       "dc390_StatusPhase",
467
       "dc390_Nop_0",
468
       "dc390_Nop_0",
469
       "dc390_MsgOutPhase",
470
       "dc390_MsgInPhase",
471
       "dc390_Nop_1"
472
       };
473
#endif   
474
 
475
/* Devices erroneously pretending to be able to do TagQ */
476
UCHAR  dc390_baddevname1[2][28] ={
477
       "SEAGATE ST3390N         9546",
478
       "HP      C3323-300       4269"};
479
#define BADDEVCNT       2
480
 
481
static char*  dc390_adapname = "DC390";
482
UCHAR  dc390_eepromBuf[MAX_ADAPTER_NUM][EE_LEN];
483
UCHAR  dc390_clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20};
484
 
485
struct proc_dir_entry   DC390_proc_scsi_tmscsim ={
486
       PROC_SCSI_DC390T, 7 ,"tmscsim",
487
       S_IFDIR | S_IRUGO | S_IXUGO, 2
488
       };
489
 
490
 
491
/***********************************************************************
492
 * Functions for access to DC390 EEPROM
493
 * and some to emulate it
494
 *
495
 **********************************************************************/
496
 
497
 
498
static void __init dc390_EnDisableCE( UCHAR mode, PDEVDECL, PUCHAR regval )
499
{
500
    UCHAR bval;
501
 
502
    bval = 0;
503
    if(mode == ENABLE_CE)
504
        *regval = 0xc0;
505
    else
506
        *regval = 0x80;
507
    PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
508
    if(mode == DISABLE_CE)
509
        PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
510
    udelay(160);
511
}
512
 
513
#ifndef CONFIG_SCSI_DC390T_NOGENSUPP
514
static void __init dc390_EEpromDefaults (UCHAR index)
515
{
516
    PUCHAR ptr;
517
    UCHAR  id;
518
    ptr = (PUCHAR) dc390_eepromBuf[index];
519
 
520
    /* Adapter Settings */
521
    ptr[EE_ADAPT_SCSI_ID] = (UCHAR)tmscsim[0]; /* Adapter ID */
522
    ptr[EE_MODE2] = (UCHAR)tmscsim[3];
523
    ptr[EE_DELAY] = 0; /* ?? */
524
    ptr[EE_TAG_CMD_NUM] = (UCHAR)tmscsim[4]; /* Tagged Comds */
525
 
526
    /* Device Settings */
527
    for (id = 0; id < MAX_SCSI_ID; id++)
528
    {
529
      ptr[id<<2] = (UCHAR)tmscsim[2]; /* EE_MODE1 */
530
      ptr[(id<<2) + 1] = (UCHAR)tmscsim[1]; /* EE_Speed */
531
    };
532
    dc390_adapname = "AM53C974";
533
}
534
 
535
static void __init dc390_checkparams (void)
536
{
537
        PARSEDEBUG(printk(KERN_INFO "DC390: setup %08x %08x %08x %08x %08x\n", tmscsim[0],\
538
                      tmscsim[1], tmscsim[2], tmscsim[3], tmscsim[4]);)
539
        if (tmscsim[0] < 0 || tmscsim[0] > 7) /* modules-2.0.0 passes -1 as string */
540
        {
541
                tmscsim[0] = 7; tmscsim[1] = 4;
542
                tmscsim[2] = 9; tmscsim[3] = 15;
543
                tmscsim[4] = 2;
544
                printk (KERN_INFO "DC390: Using safe settings.\n");
545
        }
546
        else
547
        {
548
                /* if (tmscsim[0] < 0 || tmscsim[0] > 7) tmscsim[0] = 7; */
549
                if (tmscsim[1] < 0 || tmscsim[1] > 7) tmscsim[1] = 4;
550
                if (tmscsim[4] < 0 || tmscsim[4] > 5) tmscsim[4] = 4;
551
        };
552
};
553
/* Override defaults on cmdline:
554
 * tmscsim: AdaptID, MaxSpeed (Index), DevMode (Bitmapped), AdaptMode (Bitmapped)
555
 */
556
void __init dc390_setup (char *str, int *ints)
557
{
558
        int i;
559
        for (i = 0; i < ints[0]; i++)
560
                tmscsim[i] = ints[i+1];
561
        if (ints[0] > 5)
562
                printk (KERN_NOTICE "DC390: ignore extra params!\n");
563
        /* dc390_checkparams (); */
564
};
565
#endif /* CONFIG_SCSI_DC390T_NOGENSUPP */
566
 
567
 
568
static void __init dc390_EEpromOutDI( PDEVDECL, PUCHAR regval, UCHAR Carry )
569
{
570
    UCHAR bval;
571
 
572
    bval = 0;
573
    if(Carry)
574
    {
575
        bval = 0x40;
576
        *regval = 0x80;
577
        PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
578
    }
579
    udelay(160);
580
    bval |= 0x80;
581
    PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
582
    udelay(160);
583
    bval = 0;
584
    PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
585
    udelay(160);
586
}
587
 
588
 
589
static UCHAR __init dc390_EEpromInDO( PDEVDECL )
590
{
591
    UCHAR bval;
592
 
593
    PCI_WRITE_CONFIG_BYTE(PDEV, 0x80, 0x80);
594
    udelay(160);
595
    PCI_WRITE_CONFIG_BYTE(PDEV, 0x80, 0x40);
596
    udelay(160);
597
    PCI_READ_CONFIG_BYTE(PDEV, 0x00, &bval);
598
    if(bval == 0x22)
599
        return(1);
600
    else
601
        return(0);
602
}
603
 
604
 
605
static USHORT __init dc390_EEpromGetData1( PDEVDECL )
606
{
607
    UCHAR i;
608
    UCHAR carryFlag;
609
    USHORT wval;
610
 
611
    wval = 0;
612
    for(i=0; i<16; i++)
613
    {
614
        wval <<= 1;
615
        carryFlag = dc390_EEpromInDO(PDEV);
616
        wval |= carryFlag;
617
    }
618
    return(wval);
619
}
620
 
621
 
622
static void __init dc390_Prepare( PDEVDECL, PUCHAR regval, UCHAR EEpromCmd )
623
{
624
    UCHAR i,j;
625
    UCHAR carryFlag;
626
 
627
    carryFlag = 1;
628
    j = 0x80;
629
    for(i=0; i<9; i++)
630
    {
631
        dc390_EEpromOutDI(PDEV,regval,carryFlag);
632
        carryFlag = (EEpromCmd & j) ? 1 : 0;
633
        j >>= 1;
634
    }
635
}
636
 
637
 
638
static void __init dc390_ReadEEprom( PDEVDECL, PUSHORT ptr)
639
{
640
    UCHAR   regval,cmd;
641
    UCHAR   i;
642
 
643
    cmd = EEPROM_READ;
644
    for(i=0; i<0x40; i++)
645
    {
646
        dc390_EnDisableCE(ENABLE_CE, PDEV, &regval);
647
        dc390_Prepare(PDEV, &regval, cmd++);
648
        *ptr++ = dc390_EEpromGetData1(PDEV);
649
        dc390_EnDisableCE(DISABLE_CE, PDEV, &regval);
650
    }
651
}
652
 
653
 
654
static UCHAR __init dc390_CheckEEpromCheckSum( PDEVDECL, UCHAR index )
655
{
656
    UCHAR  i;
657
    char  EEbuf[128];
658
    USHORT wval, *ptr = (PUSHORT)EEbuf;
659
 
660
    dc390_ReadEEprom( PDEV, ptr );
661
    memcpy (dc390_eepromBuf[index], EEbuf, EE_ADAPT_SCSI_ID);
662
    memcpy (&dc390_eepromBuf[index][EE_ADAPT_SCSI_ID],
663
            &EEbuf[REAL_EE_ADAPT_SCSI_ID], EE_LEN - EE_ADAPT_SCSI_ID);
664
    wval = 0;
665
    for(i=0; i<0x40; i++, ptr++)
666
        wval += *ptr;
667
    return (wval == 0x1234 ? 0 : 1);
668
}
669
 
670
 
671
/***********************************************************************
672
 * Functions for the management of the internal structures
673
 * (DCBs, SRBs, Queueing)
674
 *
675
 **********************************************************************/
676
static PDCB __inline__ dc390_findDCB ( PACB pACB, Scsi_Cmnd *cmd)
677
{
678
   PDCB pDCB = pACB->pLinkDCB; if (!pDCB) return 0;
679
   while (pDCB->UnitSCSIID != cmd->target || pDCB->UnitSCSILUN != cmd->lun)
680
     {
681
        pDCB = pDCB->pNextDCB;
682
        if (pDCB == pACB->pLinkDCB)
683
          {
684
             printk (KERN_WARNING "DC390: DCB not found (DCB=%08x, DCBmap[%2x]=%2x)\n",
685
                     (int)pDCB, cmd->target, pACB->DCBmap[cmd->target]);
686
             return 0;
687
          }
688
     };
689
   DCBDEBUG1( printk (KERN_DEBUG "DCB %08x (%02x,%02x) found.\n",       \
690
           (int)pDCB, pDCB->UnitSCSIID, pDCB->UnitSCSILUN);)
691
   return pDCB;
692
};
693
 
694
static void dc390_QLinkcmd( PSCSICMD cmd, PDCB pDCB )
695
{
696
    PSCSICMD  pcmd;
697
 
698
    if( !pDCB->QIORBCnt )
699
    {
700
        pDCB->pQIORBhead = cmd;
701
        pDCB->pQIORBtail = cmd;
702
        pDCB->QIORBCnt++;
703
        cmd->next = NULL;
704
    }
705
    else
706
    {
707
        pcmd = pDCB->pQIORBtail;
708
        pcmd->next = cmd;
709
        pDCB->pQIORBtail = cmd;
710
        pDCB->QIORBCnt++;
711
        cmd->next = NULL;
712
    }
713
 
714
}
715
 
716
 
717
static __inline__ PSCSICMD dc390_Getcmd( PDCB pDCB )
718
{
719
    PSCSICMD  pcmd;
720
 
721
    pcmd = pDCB->pQIORBhead;
722
    pDCB->pQIORBhead = pcmd->next;
723
    pcmd->next = NULL;
724
    pDCB->QIORBCnt--;
725
 
726
    return( pcmd );
727
}
728
 
729
 
730
static __inline__ PSRB dc390_GetSRB( PACB pACB )
731
{
732
    PSRB   pSRB;
733
 
734
    pSRB = pACB->pFreeSRB;
735
    if( pSRB )
736
    {
737
        pACB->pFreeSRB = pSRB->pNextSRB;
738
        pSRB->pNextSRB = NULL;
739
    }
740
 
741
    return( pSRB );
742
}
743
 
744
 
745
static __inline__ void dc390_RewaitSRB0( PDCB pDCB, PSRB pSRB )
746
{
747
    PSRB   psrb1;
748
 
749
    if( (psrb1 = pDCB->pWaitingSRB) )
750
    {
751
        pSRB->pNextSRB = psrb1;
752
    }
753
    else
754
    {
755
        pSRB->pNextSRB = NULL;
756
        pDCB->pWaitLast = pSRB;
757
    }
758
    pDCB->pWaitingSRB = pSRB;
759
}
760
 
761
 
762
static void dc390_RewaitSRB( PDCB pDCB, PSRB pSRB )
763
{
764
    PSRB   psrb1;
765
    UCHAR  bval;
766
 
767
    pDCB->GoingSRBCnt--; pDCB->pDCBACB->SelLost++;
768
    DEBUG0(printk(KERN_INFO "DC390: RewaitSRB (%p, %p) pid = %li\n", pDCB, pSRB, pSRB->pcmd->pid);)
769
    psrb1 = pDCB->pGoingSRB;
770
    if( pSRB == psrb1 )
771
    {
772
        pDCB->pGoingSRB = psrb1->pNextSRB;
773
    }
774
    else
775
    {
776
        while( pSRB != psrb1->pNextSRB )
777
            psrb1 = psrb1->pNextSRB;
778
        psrb1->pNextSRB = pSRB->pNextSRB;
779
        if( pSRB == pDCB->pGoingLast )
780
            pDCB->pGoingLast = psrb1;
781
    }
782
    if( (psrb1 = pDCB->pWaitingSRB) )
783
    {
784
        pSRB->pNextSRB = psrb1;
785
        pDCB->pWaitingSRB = pSRB;
786
    }
787
    else
788
    {
789
        pSRB->pNextSRB = NULL;
790
        pDCB->pWaitingSRB = pSRB;
791
        pDCB->pWaitLast = pSRB;
792
    }
793
 
794
    bval = pSRB->TagNumber;
795
    pDCB->TagMask &= (~(1 << bval));      /* Free TAG number */
796
}
797
 
798
 
799
static void dc390_DoWaitingSRB( PACB pACB )
800
{
801
    PDCB   ptr, ptr1;
802
    PSRB   pSRB;
803
 
804
    if( !(pACB->pActiveDCB) && !(pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) )
805
    {
806
        ptr = pACB->pDCBRunRobin;
807
        if( !ptr )
808
        {
809
            ptr = pACB->pLinkDCB;
810
            pACB->pDCBRunRobin = ptr;
811
        }
812
        ptr1 = ptr;
813
        for( ;ptr1; )
814
        {
815
            pACB->pDCBRunRobin = ptr1->pNextDCB;
816
            if( !( ptr1->MaxCommand > ptr1->GoingSRBCnt ) ||
817
                !( pSRB = ptr1->pWaitingSRB ) )
818
            {
819
                if(pACB->pDCBRunRobin == ptr)
820
                    break;
821
                ptr1 = ptr1->pNextDCB;
822
            }
823
            else
824
            {
825
                if( !dc390_StartSCSI(pACB, ptr1, pSRB) )
826
                {
827
                    ptr1->GoingSRBCnt++;
828
                    if( ptr1->pWaitLast == pSRB )
829
                    {
830
                        ptr1->pWaitingSRB = NULL;
831
                        ptr1->pWaitLast = NULL;
832
                    }
833
                    else
834
                    {
835
                        ptr1->pWaitingSRB = pSRB->pNextSRB;
836
                    }
837
                    pSRB->pNextSRB = NULL;
838
 
839
                    if( ptr1->pGoingSRB )
840
                        ptr1->pGoingLast->pNextSRB = pSRB;
841
                    else
842
                        ptr1->pGoingSRB = pSRB;
843
                    ptr1->pGoingLast = pSRB;
844
                }
845
                break;
846
            }
847
        }
848
    }
849
    return;
850
}
851
 
852
 
853
static __inline__ void dc390_SRBwaiting( PDCB pDCB, PSRB pSRB)
854
{
855
    if( pDCB->pWaitingSRB )
856
    {
857
        pDCB->pWaitLast->pNextSRB = pSRB;
858
        pSRB->pNextSRB = NULL;
859
    }
860
    else
861
    {
862
        pDCB->pWaitingSRB = pSRB;
863
    }
864
    pDCB->pWaitLast = pSRB;
865
}
866
 
867
 
868
/***********************************************************************
869
 * Function: static void dc390_SendSRB (PACB pACB, PSRB pSRB)
870
 *
871
 * Purpose: Send SCSI Request Block (pSRB) to adapter (pACB)
872
 *
873
 ***********************************************************************/
874
 
875
static void dc390_SendSRB( PACB pACB, PSRB pSRB )
876
{
877
    PDCB   pDCB;
878
 
879
    pDCB = pSRB->pSRBDCB;
880
    if( !(pDCB->MaxCommand > pDCB->GoingSRBCnt) || (pACB->pActiveDCB) ||
881
        (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV)) )
882
    {
883
        dc390_SRBwaiting(pDCB, pSRB);
884
        goto SND_EXIT;
885
    }
886
 
887
    if( pDCB->pWaitingSRB )
888
    {
889
        dc390_SRBwaiting(pDCB, pSRB);
890
/*      pSRB = GetWaitingSRB(pDCB); */  /* non-existent */
891
        pSRB = pDCB->pWaitingSRB;
892
        pDCB->pWaitingSRB = pSRB->pNextSRB;
893
        pSRB->pNextSRB = NULL;
894
    }
895
 
896
    if( !dc390_StartSCSI(pACB, pDCB, pSRB) )
897
    {
898
        pDCB->GoingSRBCnt++;
899
        if( pDCB->pGoingSRB )
900
        {
901
            pDCB->pGoingLast->pNextSRB = pSRB;
902
            pDCB->pGoingLast = pSRB;
903
        }
904
        else
905
        {
906
            pDCB->pGoingSRB = pSRB;
907
            pDCB->pGoingLast = pSRB;
908
        }
909
    }
910
    else
911
        dc390_RewaitSRB0( pDCB, pSRB );
912
 
913
SND_EXIT:
914
    return;
915
}
916
 
917
/***********************************************************************
918
 * Function: static void dc390_BuildSRB (Scsi_Cmd *pcmd, PDCB pDCB,
919
 *                                       PSRB pSRB)
920
 *
921
 * Purpose: Prepare SRB for being sent to Device DCB w/ command *pcmd
922
 *
923
 ***********************************************************************/
924
 
925
static void dc390_BuildSRB (Scsi_Cmnd* pcmd, PDCB pDCB, PSRB pSRB)
926
{
927
    pSRB->pSRBDCB = pDCB;
928
    pSRB->pcmd = pcmd;
929
    pSRB->ScsiCmdLen = pcmd->cmd_len;
930
    memcpy (pSRB->CmdBlock, pcmd->cmnd, pcmd->cmd_len);
931
 
932
    if( pcmd->use_sg )
933
    {
934
        pSRB->SGcount = (UCHAR) pcmd->use_sg;
935
        pSRB->pSegmentList = (PSGL) pcmd->request_buffer;
936
    }
937
    else if( pcmd->request_buffer )
938
    {
939
        pSRB->SGcount = 1;
940
        pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
941
        pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
942
        pSRB->Segmentx.length = pcmd->request_bufflen;
943
    }
944
    else
945
        pSRB->SGcount = 0;
946
 
947
    pSRB->SGIndex = 0;
948
    pSRB->AdaptStatus = 0;
949
    pSRB->TargetStatus = 0;
950
    pSRB->MsgCnt = 0;
951
    if( pDCB->DevType != TYPE_TAPE )
952
        pSRB->RetryCnt = 1;
953
    else
954
        pSRB->RetryCnt = 0;
955
    pSRB->SRBStatus = 0;
956
    pSRB->SRBFlag = 0;
957
    pSRB->SRBState = 0;
958
    pSRB->TotalXferredLen = 0;
959
    pSRB->SGBusAddr = 0;
960
    pSRB->SGToBeXferLen = 0;
961
    pSRB->ScsiPhase = 0;
962
    pSRB->EndMessage = 0;
963
};
964
 
965
 
966
/***********************************************************************
967
 * Function : static int DC390_queue_command (Scsi_Cmnd *cmd,
968
 *                                             void (*done)(Scsi_Cmnd *))
969
 *
970
 * Purpose : enqueues a SCSI command
971
 *
972
 * Inputs : cmd - SCSI command, done - callback function called on
973
 *          completion, with a pointer to the command descriptor.
974
 *
975
 * Returns : (depending on kernel version)
976
 * 2.0.x: always return 0
977
 * 2.1.x: old model: (use_new_eh_code == 0): like 2.0.x
978
 *        TO BE DONE:
979
 *        new model: return 0 if successful
980
 *                   return 1 if command cannot be queued (queue full)
981
 *                   command will be inserted in midlevel queue then ...
982
 *
983
 ***********************************************************************/
984
 
985
int DC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *))
986
{
987
    Scsi_Cmnd *pcmd;
988
    PDCB   pDCB;
989
    PSRB   pSRB;
990
    DC390_AFLAGS
991
    PACB   pACB = (PACB) cmd->host->hostdata;
992
 
993
 
994
    DEBUG0(/*  if(pACB->scan_devices) */        \
995
        printk(KERN_INFO "DC390: Queue Cmd=%02x,ID=%d,LUN=%d (pid=%li)\n",\
996
                cmd->cmnd[0],cmd->target,cmd->lun,cmd->pid);)
997
 
998
    DC390_LOCK_ACB;
999
 
1000
    /* Assume BAD_TARGET; will be cleared later */
1001
    cmd->result = DID_BAD_TARGET << 16;
1002
 
1003
    /* TODO: Change the policy: Alway accept TEST_UNIT_READY or INQUIRY
1004
     * commands and alloc a DCB for the device if not yet there. DCB will
1005
     * be removed in dc390_SRBdone if SEL_TIMEOUT */
1006
 
1007
    if( (pACB->scan_devices == END_SCAN) && (cmd->cmnd[0] != INQUIRY) )
1008
        pACB->scan_devices = 0;
1009
 
1010
    else if( (pACB->scan_devices) && (cmd->cmnd[0] == READ_6) )
1011
        pACB->scan_devices = 0;
1012
 
1013
    if ( ( cmd->target >= pACB->pScsiHost->max_id ) ||
1014
         (cmd->lun >= pACB->pScsiHost->max_lun) )
1015
    {
1016
/*      printk("DC390: Ignore target %d lun %d\n",
1017
                cmd->target, cmd->lun); */
1018
        DC390_UNLOCK_ACB;
1019
        done(cmd);
1020
        return( 0 );
1021
    }
1022
 
1023
    if( (pACB->scan_devices || cmd->cmnd[0] == TEST_UNIT_READY) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) )
1024
    {
1025
        pACB->DCBmap[cmd->target] |= (1 << cmd->lun);
1026
        pACB->scan_devices = 1;
1027
 
1028
        dc390_initDCB( pACB, &pDCB, cmd );
1029
        if (!pDCB)
1030
          {
1031
            printk (KERN_ERR "DC390: kmalloc for DCB failed, ID=%2x\n", cmd->target);
1032
            DC390_UNLOCK_ACB;
1033
            done(cmd);
1034
            return(0);
1035
          };
1036
 
1037
    }
1038
    else if( !(pACB->scan_devices) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) )
1039
    {
1040
        printk(KERN_INFO "DC390: Ignore target %02x lun %02x\n",
1041
                cmd->target, cmd->lun);
1042
        DC390_UNLOCK_ACB;
1043
        done(cmd);
1044
        return(0);
1045
    }
1046
    else
1047
    {
1048
        pDCB = dc390_findDCB (pACB, cmd);
1049
        if (!pDCB)
1050
         {  /* should never happen */
1051
            DC390_UNLOCK_ACB;
1052
            done(cmd);
1053
            return(0);
1054
         };
1055
    }
1056
 
1057
    pACB->Cmds++;
1058
    cmd->scsi_done = done;
1059
    cmd->result = 0;
1060
 
1061
    if( pDCB->QIORBCnt ) /* Unsent commands ? */
1062
    {
1063
        dc390_QLinkcmd( cmd, pDCB );
1064
        pcmd = dc390_Getcmd( pDCB ); /* Get first command */
1065
        pACB->CmdInQ++;
1066
    }
1067
    else
1068
        pcmd = cmd;
1069
 
1070
    pSRB = dc390_GetSRB( pACB );
1071
 
1072
    if( !pSRB )
1073
    {
1074
        dc390_QLinkcmd( pcmd, pDCB ); /* Queue command at the end */
1075
        pACB->CmdOutOfSRB++;
1076
        DC390_UNLOCK_ACB;
1077
        return(0);
1078
    }
1079
 
1080
    dc390_BuildSRB (pcmd, pDCB, pSRB);
1081
    dc390_SendSRB( pACB, pSRB );
1082
 
1083
    DC390_UNLOCK_ACB;
1084
    DEBUG1(printk (KERN_DEBUG " ... command (%02x) queued successfully.\n", pcmd->cmnd[0]);)
1085
    return(0);
1086
}
1087
 
1088
 
1089
static void dc390_DoNextCmd( PACB pACB, PDCB pDCB )
1090
{
1091
    Scsi_Cmnd *pcmd;
1092
    PSRB   pSRB;
1093
 
1094
    if( pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) )
1095
        return;
1096
 
1097
    pcmd = dc390_Getcmd( pDCB );
1098
    pSRB = dc390_GetSRB( pACB );
1099
    if( !pSRB )
1100
        dc390_QLinkcmd( pcmd, pDCB );
1101
    else
1102
      {
1103
        dc390_BuildSRB (pcmd, pDCB, pSRB);
1104
        dc390_SendSRB( pACB, pSRB );
1105
      };
1106
}
1107
 
1108
/* We ignore mapping problems, as we expect everybody to respect
1109
 * valid partition tables. Waiting for complaints ;-) */
1110
 
1111
#ifdef CONFIG_SCSI_DC390T_TRADMAP
1112
/*
1113
 * The next function, partsize(), is copied from scsicam.c.
1114
 *
1115
 * This is ugly code duplication, but I didn't find another way to solve it:
1116
 * We want to respect the partition table and if it fails, we apply the
1117
 * DC390 BIOS heuristic. Too bad, just calling scsicam_bios_param() doesn't do
1118
 * the job, because we don't know, whether the values returned are from
1119
 * the part. table or determined by setsize(). Unfortunately the setsize()
1120
 * values differ from the ones chosen by the DC390 BIOS.
1121
 *
1122
 * Looking forward to seeing suggestions for a better solution! KG, 98/10/14
1123
 */
1124
#include <asm/unaligned.h>
1125
 
1126
/*
1127
 * Function : static int partsize(struct buffer_head *bh, unsigned long
1128
 *     capacity,unsigned int *cyls, unsigned int *hds, unsigned int *secs);
1129
 *
1130
 * Purpose : to determine the BIOS mapping used to create the partition
1131
 *      table, storing the results in *cyls, *hds, and *secs
1132
 *
1133
 * Returns : -1 on failure, 0 on success.
1134
 *
1135
 */
1136
 
1137
static int partsize(struct buffer_head *bh, unsigned long capacity,
1138
    unsigned int  *cyls, unsigned int *hds, unsigned int *secs) {
1139
    struct partition *p, *largest = NULL;
1140
    int i, largest_cyl;
1141
    int cyl, ext_cyl, end_head, end_cyl, end_sector;
1142
    unsigned int logical_end, physical_end, ext_physical_end;
1143
 
1144
 
1145
    if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
1146
        for (largest_cyl = -1, p = (struct partition *)
1147
            (0x1BE + bh->b_data), i = 0; i < 4; ++i, ++p) {
1148
            if (!p->sys_ind)
1149
                continue;
1150
            cyl = p->cyl + ((p->sector & 0xc0) << 2);
1151
            if (cyl > largest_cyl) {
1152
                largest_cyl = cyl;
1153
                largest = p;
1154
            }
1155
        }
1156
    }
1157
 
1158
    if (largest) {
1159
        end_cyl = largest->end_cyl + ((largest->end_sector & 0xc0) << 2);
1160
        end_head = largest->end_head;
1161
        end_sector = largest->end_sector & 0x3f;
1162
 
1163
        physical_end =  end_cyl * (end_head + 1) * end_sector +
1164
            end_head * end_sector + end_sector;
1165
 
1166
        /* This is the actual _sector_ number at the end */
1167
        logical_end = get_unaligned(&largest->start_sect)
1168
                        + get_unaligned(&largest->nr_sects);
1169
 
1170
        /* This is for >1023 cylinders */
1171
        ext_cyl= (logical_end-(end_head * end_sector + end_sector))
1172
                                        /(end_head + 1) / end_sector;
1173
        ext_physical_end = ext_cyl * (end_head + 1) * end_sector +
1174
            end_head * end_sector + end_sector;
1175
 
1176
        if ((logical_end == physical_end) ||
1177
            (end_cyl==1023 && ext_physical_end==logical_end)) {
1178
            *secs = end_sector;
1179
            *hds = end_head + 1;
1180
            *cyls = capacity / ((end_head + 1) * end_sector);
1181
            return 0;
1182
        }
1183
    }
1184
    return -1;
1185
}
1186
 
1187
/***********************************************************************
1188
 * Function:
1189
 *   DC390_bios_param
1190
 *
1191
 * Description:
1192
 *   Return the disk geometry for the given SCSI device.
1193
 *   Respect the partition table, otherwise try own heuristic
1194
 *
1195
 * Note:
1196
 *   In contrary to other externally callable funcs (DC390_), we don't lock
1197
 ***********************************************************************/
1198
int DC390_bios_param (Disk *disk, kdev_t devno, int geom[])
1199
{
1200
    int heads, sectors, cylinders;
1201
    PACB pACB = (PACB) disk->device->host->hostdata;
1202
    struct buffer_head *bh;
1203
    int ret_code = -1;
1204
    int size = disk->capacity;
1205
 
1206
    if ((bh = bread(MKDEV(MAJOR(devno), MINOR(devno)&~0xf), 0, 1024)))
1207
    {
1208
        /* try to infer mapping from partition table */
1209
        ret_code = partsize (bh, (unsigned long) size, (unsigned int *) geom + 2,
1210
                             (unsigned int *) geom + 0, (unsigned int *) geom + 1);
1211
        brelse (bh);
1212
    }
1213
    if (ret_code == -1)
1214
    {
1215
        heads = 64;
1216
        sectors = 32;
1217
        cylinders = size / (heads * sectors);
1218
 
1219
        if ( (pACB->Gmode2 & GREATER_1G) && (cylinders > 1024) )
1220
        {
1221
                heads = 255;
1222
                sectors = 63;
1223
                cylinders = size / (heads * sectors);
1224
        }
1225
 
1226
        geom[0] = heads;
1227
        geom[1] = sectors;
1228
        geom[2] = cylinders;
1229
    }
1230
 
1231
    return (0);
1232
}
1233
#else
1234
int DC390_bios_param (Disk *disk, kdev_t devno, int geom[])
1235
{
1236
    return scsicam_bios_param (disk, devno, geom);
1237
};
1238
#endif
1239
 
1240
 
1241
void dc390_dumpinfo (PACB pACB, PDCB pDCB, PSRB pSRB)
1242
{
1243
    USHORT pstat; PDEVDECL1;
1244
 
1245
    if (pSRB)
1246
    {
1247
        printk ("DC390: SRB: Xferred %08lx, Remain %08lx, State %08lx, Phase %02x\n",
1248
                pSRB->TotalXferredLen, pSRB->SGToBeXferLen, pSRB->SRBState,
1249
                pSRB->ScsiPhase);
1250
        printk ("DC390: AdpaterStatus: %02x, SRB Status %02x\n", pSRB->AdaptStatus, pSRB->SRBStatus);
1251
    };
1252
    printk ("DC390: Status of last IRQ (DMA/SC/Int/IRQ): %08lx\n", dc390_laststatus);
1253
    printk ("DC390: Register dump: SCSI block:\n");
1254
    printk ("DC390: XferCnt  Cmd Stat IntS IRQS FFIS Ctl1 Ctl2 Ctl3 Ctl4\n");
1255
    printk ("DC390:  %06x   %02x   %02x   %02x",
1256
            DC390_read8(CtcReg_Low) + (DC390_read8(CtcReg_Mid) << 8) + (DC390_read8(CtcReg_High) << 16),
1257
            DC390_read8(ScsiCmd), DC390_read8(Scsi_Status), DC390_read8(Intern_State));
1258
    printk ("   %02x   %02x   %02x   %02x   %02x   %02x\n",
1259
            DC390_read8(INT_Status), DC390_read8(Current_Fifo), DC390_read8(CtrlReg1),
1260
            DC390_read8(CtrlReg2), DC390_read8(CtrlReg3), DC390_read8(CtrlReg4));
1261
    DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
1262
    printk ("DC390: Register dump: DMA engine:\n");
1263
    printk ("DC390: Cmd   STrCnt    SBusA    WrkBC    WrkAC Stat SBusCtrl\n");
1264
    printk ("DC390:  %02x %08x %08x %08x %08x   %02x %08x\n",
1265
            DC390_read8(DMA_Cmd), DC390_read32(DMA_XferCnt), DC390_read32(DMA_XferAddr),
1266
            DC390_read32(DMA_Wk_ByteCntr), DC390_read32(DMA_Wk_AddrCntr),
1267
            DC390_read8(DMA_Status), DC390_read32(DMA_ScsiBusCtrl));
1268
    DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
1269
    PDEVSET1; PCI_READ_CONFIG_WORD(PDEV, PCI_STATUS, &pstat);
1270
    printk ("DC390: Register dump: PCI Status: %04x\n", pstat);
1271
    printk ("DC390: In case of driver trouble read linux/drivers/scsi/README.tmscsim\n");
1272
};
1273
 
1274
 
1275
/***********************************************************************
1276
 * Function : int DC390_abort (Scsi_Cmnd *cmd)
1277
 *
1278
 * Purpose : Abort an errant SCSI command
1279
 *
1280
 * Inputs : cmd - command to abort
1281
 *
1282
 * Returns : 0 on success, -1 on failure.
1283
 *
1284
 * Status: Buggy !
1285
 ***********************************************************************/
1286
 
1287
int DC390_abort (Scsi_Cmnd *cmd)
1288
{
1289
    PDCB  pDCB;
1290
    PSRB  pSRB, psrb;
1291
    ULONG count, i;
1292
    PSCSICMD  pcmd, pcmd1;
1293
    int   status;
1294
    ULONG sbac;
1295
    DC390_AFLAGS
1296
    PACB  pACB = (PACB) cmd->host->hostdata;
1297
 
1298
    DC390_LOCK_ACB;
1299
 
1300
    pDCB = dc390_findDCB (pACB, cmd);
1301
    /* abort() is too buggy at the moment. If it's called we are in trouble anyway.
1302
     * so let's dump some info into the syslog at least. (KG, 98/08/20) */
1303
    if (pDCB) pSRB = pDCB->pActiveSRB; else pSRB = 0;
1304
    printk ("DC390: Abort command (pid %li, DCB %p, SRB %p)\n",
1305
            cmd->pid, pDCB, pSRB);
1306
    dc390_dumpinfo (pACB, pDCB, pSRB);
1307
 
1308
    if( !pDCB ) goto  NOT_RUN;
1309
 
1310
    if( pDCB->QIORBCnt )
1311
    {
1312
        pcmd = pDCB->pQIORBhead;
1313
        if( pcmd == cmd )
1314
        {
1315
            pDCB->pQIORBhead = pcmd->next;
1316
            pcmd->next = NULL;
1317
            pDCB->QIORBCnt--;
1318
            status = SCSI_ABORT_SUCCESS;
1319
            goto  ABO_X;
1320
        }
1321
        for( count = pDCB->QIORBCnt, i=0; i<count-1; i++)
1322
        {
1323
            if( pcmd->next == cmd )
1324
            {
1325
                pcmd1 = pcmd->next;
1326
                pcmd->next = pcmd1->next;
1327
                pcmd1->next = NULL;
1328
                pDCB->QIORBCnt--;
1329
                status = SCSI_ABORT_SUCCESS;
1330
                goto  ABO_X;
1331
            }
1332
            else
1333
            {
1334
                pcmd = pcmd->next;
1335
            }
1336
        }
1337
    }
1338
 
1339
    /* Added 98/07/02 KG */
1340
    pSRB = pDCB->pActiveSRB;
1341
    if (pSRB && pSRB->pcmd == cmd )
1342
        goto ON_GOING;
1343
 
1344
    pSRB = pDCB->pWaitingSRB;
1345
    if( !pSRB )
1346
        goto  ON_GOING;
1347
    if( pSRB->pcmd == cmd )
1348
    {
1349
        pDCB->pWaitingSRB = pSRB->pNextSRB;
1350
        goto  IN_WAIT;
1351
    }
1352
    else
1353
    {
1354
        psrb = pSRB;
1355
        if( !(psrb->pNextSRB) )
1356
            goto ON_GOING;
1357
        while( psrb->pNextSRB->pcmd != cmd )
1358
        {
1359
            psrb = psrb->pNextSRB;
1360
            if( !(psrb->pNextSRB) || psrb == pSRB)
1361
                goto ON_GOING;
1362
        }
1363
        pSRB = psrb->pNextSRB;
1364
        psrb->pNextSRB = pSRB->pNextSRB;
1365
        if( pSRB == pDCB->pWaitLast )
1366
            pDCB->pWaitLast = psrb; /* No check for psrb == NULL ? */
1367
IN_WAIT:
1368
        pSRB->pNextSRB = pACB->pFreeSRB;
1369
        pACB->pFreeSRB = pSRB;
1370
        cmd->next = NULL;
1371
        status = SCSI_ABORT_SUCCESS;
1372
        goto  ABO_X;
1373
    }
1374
 
1375
ON_GOING:
1376
    pSRB = pDCB->pGoingSRB;
1377
    pDCB->DCBFlag |= ABORT_DEV_;
1378
    /* Now for the hard part: The command is currently processed */
1379
    for( count = pDCB->GoingSRBCnt, i=0; i<count; i++)
1380
    {
1381
        if( pSRB->pcmd != cmd )
1382
            pSRB = pSRB->pNextSRB;
1383
        else
1384
        {
1385
            if( (pACB->pActiveDCB == pDCB) && (pDCB->pActiveSRB == pSRB) )
1386
            {
1387
                status = SCSI_ABORT_BUSY;
1388
                printk ("DC390: Abort current command (pid %li, SRB %p)\n",
1389
                        cmd->pid, pSRB);
1390
                goto  ABO_X;
1391
            }
1392
            else
1393
            {
1394
                status = SCSI_ABORT_SNOOZE;
1395
                goto  ABO_X;
1396
            }
1397
        }
1398
    }
1399
 
1400
NOT_RUN:
1401
    status = SCSI_ABORT_NOT_RUNNING;
1402
 
1403
ABO_X:
1404
    cmd->result = DID_ABORT << 16;
1405
    printk(KERN_INFO "DC390: Aborted pid %li with status %i\n", cmd->pid, status);
1406
    if (cmd->pid == dc390_lastabortedpid) /* repeated failure ? */
1407
        {
1408
                /* Let's do something to help the bus getting clean again */
1409
                DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
1410
                DC390_write8 (ScsiCmd, DMA_COMMAND);
1411
                        //DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1412
                //DC390_write8 (ScsiCmd, RESET_ATN_CMD);
1413
                DC390_write8 (ScsiCmd, NOP_CMD);
1414
                //udelay (10000);
1415
                //DC390_read8 (INT_Status);
1416
                //DC390_write8 (ScsiCmd, EN_SEL_RESEL);
1417
        };
1418
    sbac = DC390_read32 (DMA_ScsiBusCtrl);
1419
    if (sbac & SCSI_BUSY)
1420
    {   /* clear BSY, SEL and ATN */
1421
        printk (KERN_WARNING "DC390: Reset SCSI device: ");
1422
        //DC390_write32 (DMA_ScsiBusCtrl, (sbac | SCAM) & ~SCSI_LINES);
1423
        //udelay (250);
1424
        //sbac = DC390_read32 (DMA_ScsiBusCtrl);
1425
        //printk ("%08lx ", sbac);
1426
        //DC390_write32 (DMA_ScsiBusCtrl, sbac & ~(SCSI_LINES | SCAM));
1427
        //udelay (100);
1428
        //sbac = DC390_read32 (DMA_ScsiBusCtrl);
1429
        //printk ("%08lx ", sbac);
1430
        DC390_write8 (ScsiCmd, RST_DEVICE_CMD);
1431
        udelay (250);
1432
        DC390_write8 (ScsiCmd, NOP_CMD);
1433
        sbac = DC390_read32 (DMA_ScsiBusCtrl);
1434
        printk ("%08lx\n", sbac);
1435
    };
1436
    dc390_lastabortedpid = cmd->pid;
1437
    DC390_UNLOCK_ACB;
1438
    //do_DC390_Interrupt (pACB->IRQLevel, 0, 0);
1439
    cmd->scsi_done(cmd);
1440
    return( status );
1441
}
1442
 
1443
 
1444
static void dc390_ResetDevParam( PACB pACB )
1445
{
1446
    PDCB   pDCB, pdcb;
1447
 
1448
    pDCB = pACB->pLinkDCB;
1449
    if (! pDCB) return;
1450
    pdcb = pDCB;
1451
    do
1452
    {
1453
        pDCB->SyncMode &= ~SYNC_NEGO_DONE;
1454
        pDCB->SyncPeriod = 0;
1455
        pDCB->SyncOffset = 0;
1456
        pDCB->CtrlR3 = FAST_CLK;
1457
        pDCB->CtrlR4 &= NEGATE_REQACKDATA | CTRL4_RESERVED | NEGATE_REQACK;
1458
        pDCB->CtrlR4 |= pACB->glitch_cfg;
1459
        pDCB = pDCB->pNextDCB;
1460
    }
1461
    while( pdcb != pDCB );
1462
}
1463
 
1464
 
1465
static void dc390_RecoverSRB( PACB pACB )
1466
{
1467
    PDCB   pDCB, pdcb;
1468
    PSRB   psrb, psrb2;
1469
    ULONG  cnt, i;
1470
 
1471
    pDCB = pACB->pLinkDCB;
1472
    if( !pDCB ) return;
1473
    pdcb = pDCB;
1474
    do
1475
    {
1476
        cnt = pdcb->GoingSRBCnt;
1477
        psrb = pdcb->pGoingSRB;
1478
        for (i=0; i<cnt; i++)
1479
        {
1480
            psrb2 = psrb;
1481
            psrb = psrb->pNextSRB;
1482
/*          dc390_RewaitSRB( pDCB, psrb ); */
1483
            if( pdcb->pWaitingSRB )
1484
            {
1485
                psrb2->pNextSRB = pdcb->pWaitingSRB;
1486
                pdcb->pWaitingSRB = psrb2;
1487
            }
1488
            else
1489
            {
1490
                pdcb->pWaitingSRB = psrb2;
1491
                pdcb->pWaitLast = psrb2;
1492
                psrb2->pNextSRB = NULL;
1493
            }
1494
        }
1495
        pdcb->GoingSRBCnt = 0;
1496
        pdcb->pGoingSRB = NULL;
1497
        pdcb->TagMask = 0;
1498
        pdcb = pdcb->pNextDCB;
1499
    } while( pdcb != pDCB );
1500
}
1501
 
1502
 
1503
/***********************************************************************
1504
 * Function : int DC390_reset (Scsi_Cmnd *cmd, ...)
1505
 *
1506
 * Purpose : perform a hard reset on the SCSI bus
1507
 *
1508
 * Inputs : cmd - command which caused the SCSI RESET
1509
 *
1510
 * Returns : 0 on success.
1511
 ***********************************************************************/
1512
 
1513
int DC390_reset(Scsi_Cmnd *cmd, unsigned int resetFlags)
1514
{
1515
    UCHAR   bval;
1516
    ULONG   i;
1517
    DC390_AFLAGS
1518
    PACB    pACB = (PACB) cmd->host->hostdata;
1519
 
1520
    printk(KERN_INFO "DC390: RESET ... ");
1521
 
1522
    DC390_LOCK_ACB;
1523
    bval = DC390_read8 (CtrlReg1);
1524
    bval |= DIS_INT_ON_SCSI_RST;
1525
    DC390_write8 (CtrlReg1, bval);      /* disable interrupt */
1526
 
1527
    dc390_ResetSCSIBus( pACB );
1528
    /* Unlock ? */
1529
    for( i=0; i<600; i++ )
1530
        udelay(1000);
1531
 
1532
    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1533
    DC390_read8 (INT_Status);           /* Reset Pending INT */
1534
 
1535
    dc390_ResetDevParam( pACB );
1536
    dc390_DoingSRB_Done( pACB );
1537
    /* dc390_RecoverSRB (pACB); */
1538
    pACB->pActiveDCB = NULL;
1539
 
1540
    pACB->ACBFlag = 0;
1541
    bval = DC390_read8 (CtrlReg1);
1542
    bval &= ~DIS_INT_ON_SCSI_RST;
1543
    DC390_write8 (CtrlReg1, bval);      /* re-enable interrupt */
1544
 
1545
    dc390_DoWaitingSRB( pACB );
1546
 
1547
    DC390_UNLOCK_ACB;
1548
    printk("done\n");
1549
    return( SCSI_RESET_SUCCESS );
1550
}
1551
 
1552
#include "scsiiom.c"
1553
 
1554
 
1555
/***********************************************************************
1556
 * Function : static void dc390_initDCB()
1557
 *
1558
 * Purpose :  initialize the internal structures for a given DCB
1559
 *
1560
 * Inputs : cmd - pointer to this scsi cmd request block structure
1561
 ***********************************************************************/
1562
 
1563
void dc390_initDCB( PACB pACB, PDCB *ppDCB, PSCSICMD cmd )
1564
{
1565
    PEEprom     prom;
1566
    UCHAR       index;
1567
    PDCB pDCB;
1568
 
1569
    pDCB = kmalloc (sizeof(DC390_DCB), GFP_ATOMIC);
1570
    DCBDEBUG(printk (KERN_INFO "DC390: alloc mem for DCB (ID %i, LUN %i): 0x%08x\n",    \
1571
            cmd->target, cmd->lun, (int)pDCB);)
1572
 
1573
    *ppDCB = pDCB;
1574
    if (!pDCB) return;
1575
    if( pACB->DCBCnt == 0 )
1576
    {
1577
        pACB->pLinkDCB = pDCB;
1578
        pACB->pDCBRunRobin = pDCB;
1579
    }
1580
    else
1581
    {
1582
        pACB->pLastDCB->pNextDCB = pDCB;
1583
    };
1584
 
1585
    pACB->DCBCnt++;
1586
 
1587
    pACB->pLastDCB = pDCB;
1588
    pDCB->pNextDCB = pACB->pLinkDCB;
1589
 
1590
    pDCB->pDCBACB = pACB;
1591
    pDCB->QIORBCnt = 0;
1592
    pDCB->UnitSCSIID = cmd->target;
1593
    pDCB->UnitSCSILUN = cmd->lun;
1594
    pDCB->pWaitingSRB = NULL;
1595
    pDCB->pGoingSRB = NULL;
1596
    pDCB->GoingSRBCnt = 0;
1597
    pDCB->pActiveSRB = NULL;
1598
    pDCB->TagMask = 0;
1599
    pDCB->MaxCommand = 1;
1600
    index = pACB->AdapterIndex;
1601
    pDCB->DCBFlag = 0;
1602
 
1603
    prom = (PEEprom) &dc390_eepromBuf[index][cmd->target << 2];
1604
    pDCB->DevMode = prom->EE_MODE1;
1605
 
1606
    pDCB->SyncMode = 0;
1607
    dc390_updateDCB(pACB, pDCB);
1608
 
1609
    pDCB->SyncPeriod = 0;
1610
    pDCB->SyncOffset = 0;
1611
    pDCB->NegoPeriod = (dc390_clock_period1[prom->EE_SPEED] * 25) >> 2;
1612
 
1613
    pDCB->CtrlR3 = FAST_CLK;
1614
 
1615
    pDCB->CtrlR4 = pACB->glitch_cfg | CTRL4_RESERVED;
1616
    if( dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION)
1617
        pDCB->CtrlR4 |= NEGATE_REQACKDATA | NEGATE_REQACK;
1618
}
1619
 
1620
/***********************************************************************
1621
 * Function : static void dc390_updateDCB()
1622
 *
1623
 * Purpose :  Set the configuration dependent DCB parameters
1624
 ***********************************************************************/
1625
 
1626
void dc390_updateDCB (PACB pACB, PDCB pDCB)
1627
{
1628
  pDCB->IdentifyMsg = IDENTIFY (pDCB->DevMode & EN_DISCONNECT_, pDCB->UnitSCSILUN);
1629
 
1630
  if (pDCB->DevMode & TAG_QUEUEING_) pDCB->SyncMode &= EN_TAG_QUEUEING | SYNC_NEGO_DONE | EN_ATN_STOP;
1631
  else pDCB->SyncMode &= SYNC_NEGO_DONE | EN_ATN_STOP;
1632
 
1633
  if( pDCB->DevMode & SYNC_NEGO_ && (!(pDCB->UnitSCSILUN) || dc390_CurrSyncOffset) )
1634
     pDCB->SyncMode |= SYNC_ENABLE;
1635
  else
1636
     {
1637
        pDCB->SyncMode &= ~(SYNC_NEGO_DONE | SYNC_ENABLE);
1638
        pDCB->SyncOffset &= ~0x0f;
1639
     };
1640
 
1641
  if (! (pDCB->DevMode & EN_DISCONNECT_)) pDCB->SyncMode &= ~EN_ATN_STOP;
1642
 
1643
  pDCB->CtrlR1 = pACB->pScsiHost->this_id;
1644
  if( pDCB->DevMode & PARITY_CHK_ )
1645
    pDCB->CtrlR1 |= PARITY_ERR_REPO;
1646
};
1647
 
1648
 
1649
/***********************************************************************
1650
 * Function : static void dc390_updateDCBs ()
1651
 *
1652
 * Purpose :  Set the configuration dependent DCB params for all DCBs
1653
 ***********************************************************************/
1654
 
1655
static void dc390_updateDCBs (PACB pACB)
1656
{
1657
  int i;
1658
  PDCB pDCB = pACB->pLinkDCB;
1659
  for (i = 0; i < pACB->DeviceCnt; i++)
1660
    {
1661
      dc390_updateDCB (pACB, pDCB);
1662
      pDCB = pDCB->pNextDCB;
1663
    };
1664
};
1665
 
1666
 
1667
/***********************************************************************
1668
 * Function : static void dc390_initSRB()
1669
 *
1670
 * Purpose :  initialize the internal structures for a given SRB
1671
 *
1672
 * Inputs : psrb - pointer to this scsi request block structure
1673
 ***********************************************************************/
1674
 
1675
static void __inline__ dc390_initSRB( PSRB psrb )
1676
{
1677
  /* psrb->PhysSRB = virt_to_phys( psrb ); */
1678
}
1679
 
1680
 
1681
void dc390_linkSRB( PACB pACB )
1682
{
1683
    ULONG   count, i;
1684
 
1685
    count = pACB->SRBCount;
1686
    for( i=0; i< count; i++)
1687
    {
1688
        if( i != count - 1)
1689
            pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1];
1690
        else
1691
            pACB->SRB_array[i].pNextSRB = NULL;
1692
        dc390_initSRB( &pACB->SRB_array[i] );
1693
    }
1694
}
1695
 
1696
 
1697
/***********************************************************************
1698
 * Function : static void dc390_initACB ()
1699
 *
1700
 * Purpose :  initialize the internal structures for a given SCSI host
1701
 *
1702
 * Inputs : psh - pointer to this host adapter's structure
1703
 *          io_port, Irq, index: Resources and adapter index
1704
 ***********************************************************************/
1705
 
1706
void __init dc390_initACB (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index)
1707
{
1708
    PACB    pACB;
1709
    UCHAR   i;
1710
    DC390_AFLAGS
1711
 
1712
    psh->can_queue = MAX_CMD_QUEUE;
1713
    psh->cmd_per_lun = MAX_CMD_PER_LUN;
1714
    psh->this_id = (int) dc390_eepromBuf[index][EE_ADAPT_SCSI_ID];
1715
    psh->io_port = io_port;
1716
    psh->n_io_port = 0x80;
1717
    psh->irq = Irq;
1718
 
1719
    pACB = (PACB) psh->hostdata;
1720
    DC390_LOCKA_INIT;
1721
    DC390_LOCK_ACB;
1722
 
1723
    pACB->pScsiHost = psh;
1724
    pACB->IOPortBase = (USHORT) io_port;
1725
    pACB->IRQLevel = Irq;
1726
 
1727
    DEBUG0(printk (KERN_INFO "DC390: Adapter index %i, ID %i, IO 0x%08x, IRQ 0x%02x\n", \
1728
            index, psh->this_id, (int)io_port, Irq);)
1729
 
1730
    psh->max_id = 8;
1731
 
1732
    if( psh->max_id - 1 == dc390_eepromBuf[index][EE_ADAPT_SCSI_ID] )
1733
        psh->max_id--;
1734
    psh->max_lun = 1;
1735
    if( dc390_eepromBuf[index][EE_MODE2] & LUN_CHECK )
1736
        psh->max_lun = 8;
1737
 
1738
    pACB->pLinkDCB = NULL;
1739
    pACB->pDCBRunRobin = NULL;
1740
    pACB->pActiveDCB = NULL;
1741
    pACB->pFreeSRB = pACB->SRB_array;
1742
    pACB->SRBCount = MAX_SRB_CNT;
1743
    pACB->AdapterIndex = index;
1744
    pACB->status = 0;
1745
    psh->this_id = dc390_eepromBuf[index][EE_ADAPT_SCSI_ID];
1746
    pACB->DeviceCnt = 0;
1747
    pACB->DCBCnt = 0;
1748
    pACB->TagMaxNum = 2 << dc390_eepromBuf[index][EE_TAG_CMD_NUM];
1749
    pACB->ACBFlag = 0;
1750
    pACB->scan_devices = 1;
1751
    pACB->MsgLen = 0;
1752
    pACB->Ignore_IRQ = 0;
1753
    pACB->Gmode2 = dc390_eepromBuf[index][EE_MODE2];
1754
    dc390_linkSRB( pACB );
1755
    pACB->pTmpSRB = &pACB->TmpSRB;
1756
    dc390_initSRB( pACB->pTmpSRB );
1757
    for(i=0; i<MAX_SCSI_ID; i++)
1758
        pACB->DCBmap[i] = 0;
1759
    pACB->sel_timeout = SEL_TIMEOUT;
1760
    pACB->glitch_cfg = EATER_25NS;
1761
    pACB->Cmds = pACB->CmdInQ = pACB->CmdOutOfSRB = pACB->SelLost = 0;
1762
}
1763
 
1764
 
1765
/***********************************************************************
1766
 * Function : static int dc390_initAdapter ()
1767
 *
1768
 * Purpose :  initialize the SCSI chip ctrl registers
1769
 *
1770
 * Inputs : psh - pointer to this host adapter's structure
1771
 *          io_port, Irq, index: Resources
1772
 *
1773
 * Outputs: 0 on success, -1 on error
1774
 ***********************************************************************/
1775
 
1776
int __init dc390_initAdapter (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index)
1777
{
1778
    PACB   pACB, pACB2;
1779
    UCHAR  used_irq = 0, dstate;
1780
    int    i;
1781
 
1782
    pACB = (PACB) psh->hostdata;
1783
 
1784
    for ( pACB2 = dc390_pACB_start; pACB2 ; )
1785
      {
1786
        if( pACB2->IRQLevel == Irq )
1787
          {
1788
            used_irq = 1;
1789
            break;
1790
          }
1791
        else
1792
          pACB2 = pACB2->pNextACB;
1793
      }
1794
 
1795
    if (check_region (io_port, psh->n_io_port))
1796
        {
1797
            printk(KERN_ERR "DC390: register IO ports error!\n");
1798
            return( -1 );
1799
        }
1800
    else
1801
        request_region (io_port, psh->n_io_port, "tmscsim");
1802
 
1803
    DC390_read8_ (INT_Status, io_port);         /* Reset Pending INT */
1804
 
1805
    if( !used_irq )
1806
    {
1807
        if( (i = request_irq(Irq, do_DC390_Interrupt, DC390_IRQ, "tmscsim", NULL) ))
1808
            {
1809
                    printk(KERN_ERR "DC390: register IRQ error!\n");
1810
                    return( -1 );
1811
            }
1812
    }
1813
 
1814
    if( !dc390_pACB_start )
1815
      {
1816
        pACB2 = NULL;
1817
        dc390_pACB_start = pACB;
1818
        dc390_pACB_current = pACB;
1819
        pACB->pNextACB = NULL;
1820
      }
1821
    else
1822
      {
1823
        pACB2 = dc390_pACB_current;
1824
        dc390_pACB_current->pNextACB = pACB;
1825
        dc390_pACB_current = pACB;
1826
        pACB->pNextACB = NULL;
1827
      };
1828
 
1829
    DC390_write8 (CtrlReg1, DIS_INT_ON_SCSI_RST | psh->this_id);        /* Disable SCSI bus reset interrupt */
1830
 
1831
    if (pACB->Gmode2 & RST_SCSI_BUS)
1832
    {
1833
        dc390_ResetSCSIBus( pACB );
1834
        /* Unlock before ? */
1835
        for( i=0; i<600; i++ )
1836
                udelay(1000);
1837
    };
1838
    pACB->ACBFlag = 0;
1839
    DC390_read8 (INT_Status);                           /* Reset Pending INT */
1840
 
1841
    DC390_write8 (Scsi_TimeOut, SEL_TIMEOUT);           /* 250ms selection timeout */
1842
    DC390_write8 (Clk_Factor, CLK_FREQ_40MHZ);          /* Conversion factor = 0 , 40MHz clock */
1843
    DC390_write8 (ScsiCmd, NOP_CMD);                    /* NOP cmd - clear command register */
1844
    DC390_write8 (CtrlReg2, EN_FEATURE+EN_SCSI2_CMD);   /* Enable Feature and SCSI-2 */
1845
    DC390_write8 (CtrlReg3, FAST_CLK);                  /* fast clock */
1846
    DC390_write8 (CtrlReg4, pACB->glitch_cfg |                  /* glitch eater */
1847
                (dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION) ? NEGATE_REQACKDATA : 0);   /* Negation */
1848
    DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
1849
    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1850
    DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
1851
    dstate = DC390_read8 (DMA_Status);
1852
    DC390_write8 (DMA_Status, dstate);  /* clear */
1853
 
1854
    return(0);
1855
}
1856
 
1857
 
1858
/***********************************************************************
1859
 * Function : static int DC390_init (struct Scsi_Host *host, ...)
1860
 *
1861
 * Purpose :  initialize the internal structures for a given SCSI host
1862
 *
1863
 * Inputs : host - pointer to this host adapter's structure
1864
 *          io_port - IO ports mapped to this adapter
1865
 *          Irq - IRQ assigned to this adpater
1866
 *          PDEVDECL - PCI access handle
1867
 *          index - Adapter index
1868
 *
1869
 * Outputs: 0 on success, -1 on error
1870
 *
1871
 * Note: written in capitals, because the locking is only done here,
1872
 *      not in DC390_detect, called from outside
1873
 ***********************************************************************/
1874
 
1875
static int __init DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, PDEVDECL, UCHAR index)
1876
{
1877
    PSH   psh;
1878
    PACB  pACB;
1879
    DC390_AFLAGS
1880
 
1881
    if (dc390_CheckEEpromCheckSum (PDEV, index))
1882
    {
1883
#ifdef CONFIG_SCSI_DC390T_NOGENSUPP
1884
        printk (KERN_ERR "DC390_init: No EEPROM found!\n");
1885
        return( -1 );
1886
#else
1887
        int period;
1888
        printk (KERN_INFO "DC390_init: No EEPROM found!\n");
1889
        printk (KERN_INFO "DC390_init: Trying default EEPROM settings:\n");
1890
        dc390_checkparams ();
1891
        period = dc390_clock_period1[tmscsim[1]];
1892
        printk (KERN_INFO "DC390: Used defaults: AdaptID=%i, SpeedIdx=%i (%i.%i MHz),"
1893
                " DevMode=0x%02x, AdaptMode=0x%02x, TaggedCmnds=%i (%i)\n", tmscsim[0], tmscsim[1],
1894
                40 / period, ((40%period)*10 + period/2) / period,
1895
                (UCHAR)tmscsim[2], (UCHAR)tmscsim[3], tmscsim[4], 2 << (tmscsim[4]));
1896
        dc390_EEpromDefaults (index);
1897
#endif
1898
    };
1899
 
1900
    psh = scsi_register( psht, sizeof(DC390_ACB) );
1901
    if( !psh ) return( -1 );
1902
 
1903
    pACB = (PACB) psh->hostdata;
1904
    DC390_LOCKA_INIT;
1905
    DC390_LOCK_ACB;
1906
 
1907
#if 0
1908
    if( !dc390_pSH_start )
1909
    {
1910
        dc390_pSH_start = psh;
1911
        dc390_pSH_current = psh;
1912
    }
1913
    else
1914
    {
1915
        dc390_pSH_current->next = psh;
1916
        dc390_pSH_current = psh;
1917
    }
1918
#endif
1919
 
1920
    DEBUG0(printk(KERN_INFO "DC390: pSH = %8x,", (UINT) psh);)
1921
    DEBUG0(printk(" Index %02i,", index);)
1922
 
1923
    dc390_initACB( psh, io_port, Irq, index );
1924
    pACB = (PACB) psh->hostdata;
1925
 
1926
    PDEVSET;
1927
 
1928
    if( !dc390_initAdapter( psh, io_port, Irq, index ) )
1929
    {
1930
        DEBUG0(printk("\nDC390: pACB = %8x, pDCBmap = %8x, pSRB_array = %8x\n",\
1931
                (UINT) pACB, (UINT) pACB->DCBmap, (UINT) pACB->SRB_array);)
1932
        DEBUG0(printk("DC390: ACB size= %4x, DCB size= %4x, SRB size= %4x\n",\
1933
                sizeof(DC390_ACB), sizeof(DC390_DCB), sizeof(DC390_SRB) );)
1934
 
1935
        DC390_UNLOCK_ACB;
1936
        return (0);
1937
    }
1938
    else
1939
    {
1940
        //dc390_pSH_start = NULL;
1941
        scsi_unregister( psh );
1942
        DC390_UNLOCK_ACB;
1943
        return( -1 );
1944
    }
1945
}
1946
 
1947
 
1948
/***********************************************************************
1949
 * Function : int DC390_detect(Scsi_Host_Template *psht)
1950
 *
1951
 * Purpose : detects and initializes AMD53C974 SCSI chips
1952
 *           that were autoprobed, overridden on the LILO command line,
1953
 *           or specified at compile time.
1954
 *
1955
 * Inputs : psht - template for this SCSI adapter
1956
 *
1957
 * Returns : number of host adapters detected
1958
 *
1959
 ***********************************************************************/
1960
 
1961
#ifndef NEW_PCI
1962
/* Acc. to PCI 2.1 spec it's up to the driver to enable Bus mastering:
1963
 * We use pci_set_master () for 2.1.x and this func for 2.0.x:  */
1964
static void __init dc390_set_master (PDEVDECL)
1965
{
1966
        USHORT cmd;
1967
        UCHAR lat;
1968
 
1969
        PCI_READ_CONFIG_WORD (PDEV, PCI_COMMAND, &cmd);
1970
 
1971
        if (! (cmd & PCI_COMMAND_MASTER)) {
1972
                printk("PCI: Enabling bus mastering for device %02x:%02x\n",
1973
                       PCI_BUS_DEV);
1974
                cmd |= PCI_COMMAND_MASTER;
1975
                PCI_WRITE_CONFIG_WORD(PDEV, PCI_COMMAND, cmd);
1976
        }
1977
        PCI_READ_CONFIG_BYTE (PDEV, PCI_LATENCY_TIMER, &lat);
1978
        if (lat < 16 /* || lat == 255 */) {
1979
                printk("PCI: Setting latency timer of device %02x:%02x from %i to 64\n",
1980
                       PCI_BUS_DEV, lat);
1981
                PCI_WRITE_CONFIG_BYTE(PDEV, PCI_LATENCY_TIMER, 64);
1982
        }
1983
 
1984
};
1985
#endif /* ! NEW_PCI */
1986
 
1987
static void __init dc390_set_pci_cfg (PDEVDECL)
1988
{
1989
        USHORT cmd;
1990
        PCI_READ_CONFIG_WORD (PDEV, PCI_COMMAND, &cmd);
1991
        cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_IO;
1992
        PCI_WRITE_CONFIG_WORD (PDEV, PCI_COMMAND, cmd);
1993
        PCI_WRITE_CONFIG_WORD (PDEV, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY));
1994
};
1995
 
1996
 
1997
int __init DC390_detect (Scsi_Host_Template *psht)
1998
{
1999
    PDEVDECL0;
2000
    UCHAR   irq;
2001
    UINT    io_port;
2002
    DC390_IFLAGS DC390_DFLAGS
2003
 
2004
    DC390_LOCK_DRV;
2005
    //dc390_pSHT_start = psht;
2006
    dc390_pACB_start = NULL;
2007
 
2008
    if ( PCI_PRESENT )
2009
        while (PCI_FIND_DEVICE (PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974))
2010
        {
2011
            DC390_LOCK_IO;              /* Remove this when going to new eh */
2012
            PCI_GET_IO_AND_IRQ;
2013
            DEBUG0(printk(KERN_INFO "DC390(%i): IO_PORT=%04x,IRQ=%x\n", dc390_adapterCnt, (UINT) io_port, irq);)
2014
 
2015
            if( !DC390_init(psht, io_port, irq, PDEV, dc390_adapterCnt))
2016
            {
2017
                PCI_SET_MASTER;
2018
                dc390_set_pci_cfg (PDEV);
2019
                dc390_adapterCnt++;
2020
            };
2021
            DC390_UNLOCK_IO;            /* Remove when going to new eh */
2022
        }
2023
    else
2024
        printk (KERN_ERR "DC390: No PCI BIOS found!\n");
2025
 
2026
    if (dc390_adapterCnt)
2027
        psht->proc_dir = &DC390_proc_scsi_tmscsim;
2028
 
2029
    printk(KERN_INFO "DC390: %i adapters found\n", dc390_adapterCnt);
2030
    DC390_UNLOCK_DRV;
2031
    return( dc390_adapterCnt );
2032
}
2033
 
2034
 
2035
/***********************************************************************
2036
 * Functions: dc390_inquiry(), dc390_inquiry_done()
2037
 *
2038
 * Purpose: When changing speed etc., we have to issue an INQUIRY
2039
 *          command to make sure, we agree upon the nego parameters
2040
 *          with the device
2041
 ***********************************************************************/
2042
 
2043
static void dc390_inquiry_done (Scsi_Cmnd* cmd)
2044
{
2045
   printk (KERN_INFO "DC390: INQUIRY (ID %02x LUN %02x) returned %08x\n",
2046
           cmd->target, cmd->lun, cmd->result);
2047
   if (cmd->result)
2048
   {
2049
        PACB pACB = (PACB)cmd->host->hostdata;
2050
        PDCB pDCB = dc390_findDCB (pACB, cmd);
2051
        printk ("DC390: Unsetting DsCn, Sync and TagQ!\n");
2052
        if (pDCB)
2053
        {
2054
                pDCB->DevMode &= ~(SYNC_NEGO_ | TAG_QUEUEING_ | EN_DISCONNECT_ );
2055
                dc390_updateDCB (pACB, pDCB);
2056
        };
2057
   };
2058
   kfree (cmd->buffer);
2059
   kfree (cmd);
2060
};
2061
 
2062
void dc390_inquiry (PACB pACB, PDCB pDCB)
2063
{
2064
   char* buffer;
2065
   Scsi_Cmnd* cmd;
2066
   buffer = kmalloc (256, GFP_ATOMIC);
2067
   cmd = kmalloc (sizeof (Scsi_Cmnd), GFP_ATOMIC);
2068
 
2069
   memset (buffer, 0, 256);
2070
   memset (cmd, 0, sizeof(Scsi_Cmnd));
2071
   cmd->cmnd[0] = INQUIRY;
2072
   cmd->cmnd[1] = (pDCB->UnitSCSILUN << 5) & 0xe0;
2073
   cmd->cmnd[4] = 0xff;
2074
 
2075
   cmd->cmd_len = 6; cmd->old_cmd_len = 6;
2076
   cmd->host = pACB->pScsiHost;
2077
   cmd->target = pDCB->UnitSCSIID;
2078
   cmd->lun = pDCB->UnitSCSILUN;
2079
   cmd->serial_number = 1;
2080
   cmd->bufflen = 128;
2081
   cmd->buffer = buffer;
2082
   cmd->request_bufflen = 128;
2083
   cmd->request_buffer = &buffer[128];
2084
   cmd->done = dc390_inquiry_done;
2085
   cmd->scsi_done = dc390_inquiry_done;
2086
   cmd->timeout_per_command = HZ;
2087
 
2088
   cmd->request.rq_status = RQ_SCSI_BUSY;
2089
 
2090
   printk (KERN_INFO "DC390: Queue INQUIRY command to dev ID %02x LUN %02x\n",
2091
           pDCB->UnitSCSIID, pDCB->UnitSCSILUN);
2092
   DC390_queue_command (cmd, dc390_inquiry_done);
2093
};
2094
 
2095
/********************************************************************
2096
 * Function: dc390_set_info()
2097
 *
2098
 * Purpose: Change adapter config
2099
 *
2100
 * Strings are parsed similar to the output of tmscsim_proc_info ()
2101
 * '-' means no change
2102
 *******************************************************************/
2103
 
2104
static int dc390_scanf (char** p1, char** p2, int* var)
2105
{
2106
   *p2 = *p1;
2107
   *var = simple_strtoul (*p2, p1, 10);
2108
   if (*p2 == *p1) return -1;
2109
   *p1 = strtok (0, " \t\n:=,;.");
2110
   return 0;
2111
};
2112
 
2113
#define SCANF(p1, p2, var, min, max)            \
2114
if (dc390_scanf (&p1, &p2, &var)) goto einv;    \
2115
else if (var<min || var>max) goto einv2
2116
 
2117
static int dc390_yesno (char** p, char* var, char bmask)
2118
{
2119
   switch (**p)
2120
     {
2121
      case 'Y': *var |= bmask; break;
2122
      case 'N': *var &= ~bmask; break;
2123
      case '-': break;
2124
      default: return -1;
2125
     }
2126
   *p = strtok (0, " \t\n:=,;");
2127
   return 0;
2128
};
2129
 
2130
#define YESNO(p, var, bmask)                    \
2131
if (dc390_yesno (&p, &var, bmask)) goto einv;   \
2132
else dc390_updateDCB (pACB, pDCB);              \
2133
if (!p) goto ok
2134
 
2135
static int dc390_search (char **p1, char **p2, char *var, char* txt, int max, int scale, char* ign)
2136
{
2137
   int dum;
2138
   if (! memcmp (*p1, txt, strlen(txt)))
2139
     {
2140
        *p2 = strtok (0, " \t\n:=,;");
2141
        if (!*p2) return -1;
2142
        dum = simple_strtoul (*p2, p1, 10);
2143
        if (*p2 == *p1) return -1;
2144
        if (dum >= 0 && dum <= max)
2145
          { *var = (dum * 100) / scale; }
2146
        else return -2;
2147
        *p1 = strtok (0, " \t\n:=,;");
2148
        if (*ign && *p1 && strlen(*p1) >= strlen(ign) &&
2149
            !(memcmp (*p1, ign, strlen(ign))))
2150
                *p1 = strtok (0, " \t\n:=,;");
2151
 
2152
     }
2153
   return 0;
2154
};
2155
 
2156
#define SEARCH(p1, p2, var, txt, max)                                           \
2157
if (dc390_search (&p1, &p2, (PUCHAR)(&var), txt, max, 100, "")) goto einv2;     \
2158
else if (!p1) goto ok2
2159
 
2160
#define SEARCH2(p1, p2, var, txt, max, scale)                                   \
2161
if (dc390_search (&p1, &p2, &var, txt, max, scale, "")) goto einv2;             \
2162
else if (!p1) goto ok2
2163
 
2164
#define SEARCH3(p1, p2, var, txt, max, scale, ign)                              \
2165
if (dc390_search (&p1, &p2, &var, txt, max, scale, ign)) goto einv2;            \
2166
else if (!p1) goto ok2
2167
 
2168
 
2169
#ifdef DC390_PARSEDEBUG
2170
static char _prstr[256];
2171
char* prstr (char* p, char* e)
2172
{
2173
   char* c = _prstr;
2174
   while (p < e)
2175
     if (*p == 0) { *c++ = ':'; p++; }
2176
     else if (*p == 10) { *c++ = '\\'; *c++ = 'n'; p++; }
2177
     else *c++ = *p++;
2178
   *c = 0;
2179
   return _prstr;
2180
};
2181
#endif
2182
 
2183
int dc390_set_info (char *buffer, int length, PACB pACB)
2184
{
2185
  char *pos = buffer, *p0 = buffer;
2186
  char needs_inquiry = 0;
2187
  int dum = 0;
2188
  char dev;
2189
  PDCB pDCB = pACB->pLinkDCB;
2190
  DC390_IFLAGS
2191
  DC390_AFLAGS
2192
  pos[length] = 0;
2193
 
2194
  DC390_LOCK_IO;
2195
  DC390_LOCK_ACB;
2196
  /* UPPERCASE */
2197
  /* Don't use kernel toupper, because of 2.0.x bug: ctmp unexported */
2198
  while (*pos)
2199
    { if (*pos >='a' && *pos <= 'z') *pos = *pos + 'A' - 'a'; pos++; };
2200
 
2201
  /* We should protect __strtok ! */
2202
  /* spin_lock (strtok_lock); */
2203
 
2204
  /* Remove WS */
2205
  pos = strtok (buffer, " \t:\n=,;");
2206
  if (!pos) goto ok;
2207
 
2208
 next:
2209
  if (!memcmp (pos, "RESET", 5)) goto reset;
2210
  else if (!memcmp (pos, "INQUIRY", 7)) goto inquiry;
2211
  else if (!memcmp (pos, "REMOVE", 6)) goto remove;
2212
 
2213
  if (isdigit (*pos))
2214
    {
2215
      /* Device config line */
2216
      int dev, id, lun; char* pdec;
2217
      char olddevmode;
2218
 
2219
      SCANF (pos, p0, dev, 0, pACB->DCBCnt-1);
2220
      if (pos) { SCANF (pos, p0, id, 0, 7); } else goto einv;
2221
      if (pos) { SCANF (pos, p0, lun, 0, 7); } else goto einv;
2222
      if (!pos) goto einv;
2223
 
2224
      PARSEDEBUG(printk (KERN_INFO "DC390: config line %i %i %i:\"%s\"\n", dev, id, lun, prstr (pos, &buffer[length]));)
2225
      pDCB = pACB->pLinkDCB;
2226
      for (dum = 0; dum < dev; dum++) pDCB = pDCB->pNextDCB;
2227
      /* Sanity Check */
2228
      if (pDCB->UnitSCSIID != id || pDCB->UnitSCSILUN != lun)
2229
         {
2230
            printk (KERN_ERR "DC390: no such device: Idx=%02i ID=%02i LUN=%02i\n",
2231
                    dev, id, lun);
2232
            goto einv2;
2233
         };
2234
 
2235
      olddevmode = pDCB->DevMode;
2236
      YESNO (pos, pDCB->DevMode, PARITY_CHK_);
2237
      needs_inquiry++;
2238
      YESNO (pos, pDCB->DevMode, SYNC_NEGO_);
2239
      if ((olddevmode & SYNC_NEGO_) == (pDCB->DevMode & SYNC_NEGO_)) needs_inquiry--;
2240
      needs_inquiry++;
2241
      YESNO (pos, pDCB->DevMode, EN_DISCONNECT_);
2242
      if ((olddevmode & EN_DISCONNECT_) == (pDCB->DevMode & EN_DISCONNECT_)) needs_inquiry--;
2243
      YESNO (pos, pDCB->DevMode, SEND_START_);
2244
      needs_inquiry++;
2245
      YESNO (pos, pDCB->DevMode, TAG_QUEUEING_);
2246
      if ((olddevmode & TAG_QUEUEING_) == (pDCB->DevMode & TAG_QUEUEING_)) needs_inquiry--;
2247
      YESNO (pos, pDCB->SyncMode, EN_ATN_STOP);
2248
 
2249
      dc390_updateDCB (pACB, pDCB);
2250
      if (!pos) goto ok;
2251
 
2252
      olddevmode = pDCB->NegoPeriod;
2253
      /* Look for decimal point (Speed) */
2254
      pdec = pos;
2255
      while (pdec++ < &buffer[length]) if (*pdec == '.') break;
2256
      /* NegoPeriod */
2257
      if (*pos != '-')
2258
        {
2259
          SCANF (pos, p0, dum, 72, 800);
2260
          pDCB->NegoPeriod = dum >> 2;
2261
          if (pDCB->NegoPeriod != olddevmode) needs_inquiry++;
2262
          if (!pos) goto ok;
2263
          if (memcmp (pos, "NS", 2) == 0) pos = strtok (0, " \t\n:=,;.");
2264
        }
2265
      else pos = strtok (0, " \t\n:=,;.");
2266
      if (!pos) goto ok;
2267
 
2268
      /* Speed: NegoPeriod */
2269
      if (*pos != '-')
2270
        {
2271
          SCANF (pos, p0, dum, 1, 13);
2272
          pDCB->NegoPeriod = (1000/dum) >> 2;
2273
          if (pDCB->NegoPeriod != olddevmode && !pos) needs_inquiry++;
2274
          if (!pos) goto ok;
2275
          /* decimal */
2276
          if (pos-1 == pdec)
2277
             {
2278
                int dumold = dum;
2279
                dum = simple_strtoul (pos, &p0, 10) * 10;
2280
                for (; p0-pos > 1; p0--) dum /= 10;
2281
                pDCB->NegoPeriod = (100000/(100*dumold + dum)) >> 2;
2282
                if (pDCB->NegoPeriod < 19) pDCB->NegoPeriod = 19;
2283
                if (pDCB->NegoPeriod != olddevmode) needs_inquiry++;
2284
                pos = strtok (0, " \t\n:=,;");
2285
                if (!pos) goto ok;
2286
             };
2287
          if (*pos == 'M') pos = strtok (0, " \t\n:=,;");
2288
        }
2289
      else pos = strtok (0, " \t\n:=,;");
2290
      /* dc390_updateDCB (pACB, pDCB); */
2291
      if (!pos) goto ok;
2292
 
2293
      olddevmode = pDCB->SyncOffset;
2294
      /* SyncOffs */
2295
      if (*pos != '-')
2296
        {
2297
          SCANF (pos, p0, dum, 0, 0x0f);
2298
          pDCB->SyncOffset = dum;
2299
          if (pDCB->SyncOffset > olddevmode) needs_inquiry++;
2300
        }
2301
      else pos = strtok (0, " \t\n:=,;");
2302
      dc390_updateDCB (pACB, pDCB);
2303
    }
2304
  else
2305
    {
2306
      char* p1 = pos; UCHAR dum;
2307
      PARSEDEBUG(printk (KERN_INFO "DC390: chg adapt cfg \"%s\"\n", prstr (pos, &buffer[length]));)
2308
      dum = GLITCH_TO_NS (pACB->glitch_cfg);
2309
      /* Adapter setting */
2310
      SEARCH (pos, p0, pACB->pScsiHost->max_id, "MAXID", 8);
2311
      SEARCH (pos, p0, pACB->pScsiHost->max_lun, "MAXLUN", 8);
2312
      SEARCH (pos, p0, pACB->pScsiHost->this_id, "ADAPTERID", 7);
2313
      SEARCH (pos, p0, pACB->TagMaxNum, "TAGMAXNUM", 32);
2314
      SEARCH (pos, p0, pACB->ACBFlag, "ACBFLAG", 255);
2315
      SEARCH3 (pos, p0, dum, "GLITCHEATER", 40, 1000, "NS");
2316
      SEARCH3 (pos, p0, pACB->sel_timeout, "SELTIMEOUT", 400, 163, "MS");
2317
    ok2:
2318
      pACB->glitch_cfg = NS_TO_GLITCH (dum);
2319
      if (pACB->sel_timeout < 60) pACB->sel_timeout = 60;
2320
      dum = 0; while (1 << dum <= pACB->TagMaxNum) dum ++;
2321
      pACB->TagMaxNum &= (1 << --dum);
2322
      if (pos == p1) goto einv;
2323
      dc390_updateDCBs (pACB);
2324
    }
2325
  if (pos) goto next;
2326
 
2327
 ok:
2328
  /* spin_unlock (strtok_lock); */
2329
  DC390_UNLOCK_ACB;
2330
  if (needs_inquiry)
2331
     { dc390_updateDCB (pACB, pDCB); dc390_inquiry (pACB, pDCB); };
2332
  DC390_UNLOCK_IO;
2333
  return (length);
2334
 
2335
 einv2:
2336
  pos = p0;
2337
 einv:
2338
  /* spin_unlock (strtok_lock); */
2339
  DC390_UNLOCK_ACB;
2340
  DC390_UNLOCK_IO;
2341
  printk (KERN_WARNING "DC390: parse error near \"%s\"\n", (pos? pos: "NULL"));
2342
  return (-EINVAL);
2343
 
2344
 reset:
2345
     {
2346
        Scsi_Cmnd cmd; cmd.host = pACB->pScsiHost;
2347
        printk (KERN_WARNING "DC390: Driver reset requested!\n");
2348
        DC390_UNLOCK_ACB;
2349
        DC390_reset (&cmd, 0);
2350
        DC390_UNLOCK_IO;
2351
     };
2352
  return (length);
2353
 
2354
 inquiry:
2355
     {
2356
        pos = strtok (0, " \t\n.:;="); if (!pos) goto einv;
2357
        dev = simple_strtoul (pos, &p0, 10);
2358
        if (dev >= pACB->DCBCnt) goto einv_dev;
2359
        for (dum = 0; dum < dev; dum++) pDCB = pDCB->pNextDCB;
2360
        printk (KERN_NOTICE " DC390: Issue INQUIRY command to Dev(Idx) %i SCSI ID %i LUN %i\n",
2361
                dev, pDCB->UnitSCSIID, pDCB->UnitSCSILUN);
2362
        DC390_UNLOCK_ACB;
2363
        dc390_inquiry (pACB, pDCB);
2364
        DC390_UNLOCK_IO;
2365
     };
2366
   return (length);
2367
 
2368
 remove:
2369
     {
2370
        pos = strtok (0, " \t\n.:;="); if (!pos) goto einv;
2371
        dev = simple_strtoul (pos, &p0, 10);
2372
        if (dev >= pACB->DCBCnt) goto einv_dev;
2373
        for (dum = 0; dum < dev; dum++) pDCB = pDCB->pNextDCB;
2374
        printk (KERN_NOTICE " DC390: Remove DCB for Dev(Idx) %i SCSI ID %i LUN %i\n",
2375
                dev, pDCB->UnitSCSIID, pDCB->UnitSCSILUN);
2376
        dc390_remove_dev (pACB, pDCB);
2377
        DC390_UNLOCK_ACB;
2378
        DC390_UNLOCK_IO;
2379
     };
2380
   return (length);
2381
 
2382
 einv_dev:
2383
   printk (KERN_WARNING "DC390: Ignore cmnd to illegal Dev(Idx) %i. Valid range: 0 - %i.\n",
2384
           dev, pACB->DCBCnt - 1);
2385
   DC390_UNLOCK_ACB;
2386
   DC390_UNLOCK_IO;
2387
   return (-EINVAL);
2388
 
2389
 
2390
}
2391
 
2392
#undef SEARCH
2393
#undef YESNO
2394
#undef SCANF
2395
 
2396
/********************************************************************
2397
 * Function: DC390_proc_info(char* buffer, char **start,
2398
 *                           off_t offset, int length, int hostno, int inout)
2399
 *
2400
 * Purpose: return SCSI Adapter/Device Info
2401
 *
2402
 * Input: buffer: Pointer to a buffer where to write info
2403
 *        start :
2404
 *        offset:
2405
 *        hostno: Host adapter index
2406
 *        inout : Read (=0) or set(!=0) info
2407
 *
2408
 * Output: buffer: contains info
2409
 *         length; length of info in buffer
2410
 *
2411
 * return value: length
2412
 *
2413
 ********************************************************************/
2414
 
2415
#undef SPRINTF
2416
#define SPRINTF(args...) pos += sprintf(pos, ## args)
2417
 
2418
#define YESNO(YN)               \
2419
 if (YN) SPRINTF(" Yes ");      \
2420
 else SPRINTF(" No  ")
2421
 
2422
 
2423
int DC390_proc_info (char *buffer, char **start,
2424
                     off_t offset, int length, int hostno, int inout)
2425
{
2426
  int dev, spd, spd1;
2427
  char *pos = buffer;
2428
  PSH shpnt;
2429
  PACB pACB;
2430
  PDCB pDCB;
2431
  DC390_AFLAGS
2432
 
2433
  pACB = dc390_pACB_start;
2434
 
2435
  while(pACB != (PACB)-1)
2436
     {
2437
        shpnt = pACB->pScsiHost;
2438
        if (shpnt->host_no == hostno) break;
2439
        pACB = pACB->pNextACB;
2440
     }
2441
 
2442
  if (pACB == (PACB)-1) return(-ESRCH);
2443
  if(!shpnt) return(-ESRCH);
2444
 
2445
  if(inout) /* Has data been written to the file ? */
2446
      return dc390_set_info(buffer, length, pACB);
2447
 
2448
  SPRINTF("Tekram DC390/AM53C974 PCI SCSI Host Adapter, ");
2449
  SPRINTF("Driver Version %s\n", DC390_VERSION);
2450
 
2451
  DC390_LOCK_ACB;
2452
 
2453
  SPRINTF("SCSI Host Nr %i, ", shpnt->host_no);
2454
  SPRINTF("%s Adapter Nr %i\n", dc390_adapname, pACB->AdapterIndex);
2455
  SPRINTF("IOPortBase 0x%04x, ", pACB->IOPortBase);
2456
  SPRINTF("IRQLevel 0x%02x\n", pACB->IRQLevel);
2457
 
2458
  SPRINTF("MaxID %i, MaxLUN %i, ", shpnt->max_id, shpnt->max_lun);
2459
  SPRINTF("AdapterID %i, SelTimeout %i ms\n",
2460
          shpnt->this_id, (pACB->sel_timeout*164)/100);
2461
 
2462
  SPRINTF("TagMaxNum %i, Status %i, ACBFlag %i, GlitchEater %i ns\n",
2463
          pACB->TagMaxNum, pACB->status, pACB->ACBFlag, GLITCH_TO_NS(pACB->glitch_cfg)*12);
2464
 
2465
  SPRINTF("Statistics: Cmnds %li, Cmnds not sent directly %li, Out of SRB conds %li\n",
2466
          pACB->Cmds, pACB->CmdInQ, pACB->CmdOutOfSRB);
2467
  SPRINTF("            Lost arbitrations %li\n", pACB->SelLost);
2468
 
2469
  SPRINTF("Nr of attached devices: %i, Nr of DCBs: %i\n", pACB->DeviceCnt, pACB->DCBCnt);
2470
 
2471
  SPRINTF("Idx ID LUN Prty Sync DsCn SndS TagQ STOP NegoPeriod SyncSpeed SyncOffs\n");
2472
 
2473
  pDCB = pACB->pLinkDCB;
2474
  for (dev = 0; dev < pACB->DCBCnt; dev++)
2475
     {
2476
      SPRINTF("%02i  %02i  %02i ", dev, pDCB->UnitSCSIID, pDCB->UnitSCSILUN);
2477
      YESNO(pDCB->DevMode & PARITY_CHK_);
2478
      YESNO(pDCB->SyncMode & SYNC_NEGO_DONE);
2479
      YESNO(pDCB->DevMode & EN_DISCONNECT_);
2480
      //YESNO(pDCB->SyncMode & EN_ATN_STOP);
2481
      YESNO(pDCB->DevMode & SEND_START_);
2482
      YESNO(pDCB->SyncMode & EN_TAG_QUEUEING);
2483
      YESNO(pDCB->SyncMode & EN_ATN_STOP);
2484
      if (pDCB->SyncOffset & 0x0f)
2485
      {
2486
         int sp = pDCB->SyncPeriod; if (! (pDCB->CtrlR3 & FAST_SCSI)) sp++;
2487
         SPRINTF("  %03i ns ", (pDCB->NegoPeriod) << 2);
2488
         spd = 40/(sp); spd1 = 40%(sp);
2489
         spd1 = (spd1 * 10 + sp/2) / (sp);
2490
         SPRINTF("   %2i.%1i M      %02i\n", spd, spd1, (pDCB->SyncOffset & 0x0f));
2491
      }
2492
      else SPRINTF(" (%03i ns)\n", (pDCB->NegoPeriod) << 2);
2493
      /* Add more info ...*/
2494
      pDCB = pDCB->pNextDCB;
2495
     }
2496
 
2497
  DC390_UNLOCK_ACB;
2498
  *start = buffer + offset;
2499
 
2500
  if (pos - buffer < offset)
2501
    return 0;
2502
  else if (pos - buffer - offset < length)
2503
    return pos - buffer - offset;
2504
  else
2505
    return length;
2506
}
2507
 
2508
#undef YESNO
2509
#undef SPRINTF
2510
 
2511
#ifdef MODULE
2512
 
2513
/***********************************************************************
2514
 * Function : static int dc390_shutdown (struct Scsi_Host *host)
2515
 *
2516
 * Purpose : does a clean (we hope) shutdown of the SCSI chip.
2517
 *           Use prior to dumping core, unloading the driver, etc.
2518
 *
2519
 * Returns : 0 on success
2520
 ***********************************************************************/
2521
static int dc390_shutdown (struct Scsi_Host *host)
2522
{
2523
    UCHAR    bval;
2524
    PACB pACB = (PACB)(host->hostdata);
2525
 
2526
/*  pACB->soft_reset(host); */
2527
 
2528
    printk(KERN_INFO "DC390: shutdown\n");
2529
 
2530
    pACB->ACBFlag = RESET_DONE;
2531
    bval = DC390_read8 (CtrlReg1);
2532
    bval |= DIS_INT_ON_SCSI_RST;
2533
    DC390_write8 (CtrlReg1, bval);      /* disable interrupt */
2534
    if (pACB->Gmode2 & RST_SCSI_BUS)
2535
                dc390_ResetSCSIBus (pACB);
2536
 
2537
    return( 0 );
2538
}
2539
 
2540
void dc390_freeDCBs (struct Scsi_Host *host)
2541
{
2542
    PDCB pDCB, nDCB;
2543
    PACB pACB = (PACB)(host->hostdata);
2544
 
2545
    pDCB = pACB->pLinkDCB;
2546
    if (!pDCB) return;
2547
    do
2548
    {
2549
        nDCB = pDCB->pNextDCB;
2550
        DCBDEBUG(printk (KERN_INFO "DC390: Free DCB (ID %i, LUN %i): 0x%08x\n",\
2551
                pDCB->UnitSCSIID, pDCB->UnitSCSILUN, (int)pDCB);)
2552
        kfree (pDCB);
2553
        pDCB = nDCB;
2554
    } while (pDCB && pDCB != pACB->pLinkDCB);
2555
 
2556
};
2557
 
2558
int DC390_release(struct Scsi_Host *host)
2559
{
2560
    int irq_count;
2561
    PACB pACB;
2562
    DC390_AFLAGS DC390_IFLAGS
2563
#if USE_SPINLOCKS > 1
2564
    PACB pACB = (PACB)(host->hostdata);
2565
#endif
2566
 
2567
    DC390_LOCK_IO;
2568
    DC390_LOCK_ACB;
2569
 
2570
    dc390_shutdown (host);
2571
 
2572
    if (host->irq != IRQ_NONE)
2573
    {
2574
        for (irq_count = 0, pACB = dc390_pACB_start;
2575
             pACB; pACB = pACB->pNextACB)
2576
        {
2577
            if ( pACB->IRQLevel == host->irq )
2578
                ++irq_count;
2579
        }
2580
        if (irq_count == 1)
2581
         {
2582
            DEBUG0(printk(KERN_INFO "DC390: Free IRQ %i\n",host->irq);)
2583
            free_irq(host->irq,NULL);
2584
         }
2585
    }
2586
 
2587
    release_region(host->io_port,host->n_io_port);
2588
    dc390_freeDCBs (host);
2589
    DC390_UNLOCK_ACB;
2590
    DC390_UNLOCK_IO;
2591
    return( 1 );
2592
}
2593
 
2594
Scsi_Host_Template driver_template = DC390_T;
2595
#include "scsi_module.c"
2596
#endif /* def MODULE */

powered by: WebSVN 2.1.0

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