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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * sim710.c - Copyright (C) 1999 Richard Hirst <richard@sleepie.demon.co.uk>
3
 *
4
 *----------------------------------------------------------------------------
5
 *  This program is free software; you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
7
 *  the Free Software Foundation; either version 2 of the License, or
8
 *  (at your option) any later version.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, write to the Free Software
17
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
 *----------------------------------------------------------------------------
19
 *
20
 * MCA card detection code by Trent McNair.
21
 * Fixes to not explicitly nul bss data from Xavier Bestel.
22
 * Some multiboard fixes from Rolf Eike Beer.
23
 * Auto probing of EISA config space from Trevor Hemsley.
24
 *
25
 * Various bits of code in this driver have been copied from 53c7,8xx,c,
26
 * which is coyright Drew Eckhardt.  The scripts for the SCSI chip are
27
 * compiled with the script compiler written by Drew.
28
 *
29
 * This is a simple driver for the NCR53c710.  More complex drivers
30
 * for this chip (e.g. 53c7xx.c) require that the scsi chip be able to
31
 * do DMA block moves between memory and on-chip registers, which can
32
 * be a problem if those registers are in the I/O address space.  There
33
 * can also be problems on hardware where the registers are memory
34
 * mapped, if the design is such that memory-to-memory transfers initiated
35
 * by the scsi chip cannot access the chip registers.
36
 *
37
 * This driver is designed to avoid these problems and is intended to
38
 * work with any Intel machines using 53c710 chips, including various
39
 * Compaq and NCR machines.  It was initially written for the Tadpole
40
 * TP34V VME board which is 68030 based.
41
 *
42
 * The driver supports boot-time parameters similar to
43
 *      sim710=addr:0x9000,irq:15
44
 * and insmod parameters similar to
45
 *      sim710="addr:0x9000 irq:15"
46
 *
47
 * Multiple controllers can also be set up by command line, provided the
48
 * addr: parameter is specified first for each controller.  e.g.
49
 *      sim710="addr:0x9000 irq:15 addr:0x8000 irq:14"
50
 *
51
 * To seperate the different options, ' ', '+', and ',' can be used, except
52
 * that ',' can not be used in module parameters.  ' ' can be a pain, because
53
 * it needs to be quoted, which causes problems with some installers.
54
 * The command line above is completely equivalent to
55
 *      sim710="addr:0x9000+irq:15+addr:0x8000+irq:14"
56
 *
57
 * The complete list of options are:
58
 *
59
 * addr:0x9000          Specifies the base I/O port (or address) of the 53C710.
60
 * irq:15               Specifies the IRQ number used by the 53c710.
61
 * debug:0xffff         Generates lots of debug output.
62
 * ignore:0x0a          Makes the driver ignore SCSI IDs 0 and 2.
63
 * nodisc:0x70          Prevents disconnects from IDs 6, 5 and 4.
64
 * noneg:0x10           Prevents SDTR negotiation on ID 4.
65
 * disabled:1           Completely disables the driver. When present, overrides
66
 *                      all other options.
67
 *
68
 * The driver will auto-probe chip addresses and IRQs now, so typically no
69
 * parameters are needed.  Auto-probing of addresses is disabled if any addr:
70
 * parameters are specified.
71
 *
72
 * Current limitations:
73
 *
74
 * o  Async only
75
 * o  Severely lacking in error recovery
76
 * o  'debug:' should be per host really.
77
 *
78
 */
79
 
80
#include <linux/config.h>
81
#include <linux/module.h>
82
 
83
#include <linux/version.h>
84
#include <linux/kernel.h>
85
#include <linux/types.h>
86
#include <linux/string.h>
87
#include <linux/ioport.h>
88
#include <linux/delay.h>
89
#include <linux/sched.h>
90
#include <linux/proc_fs.h>
91
#include <linux/init.h>
92
#include <linux/mca.h>
93
#include <linux/interrupt.h>
94
#include <asm/dma.h>
95
#include <asm/system.h>
96
#include <linux/spinlock.h>
97
#include <asm/io.h>
98
#include <asm/pgtable.h>
99
#include <asm/byteorder.h>
100
#include <linux/blk.h>
101
 
102
/* All targets are I/O mapped at the moment */
103
#define IO_MAPPED
104
 
105
#if defined(CONFIG_MCA)
106
 
107
/*
108
 * For each known microchannel card using the 53c710 we need a list
109
 * of possible IRQ and IO settings, as well as their corresponding
110
 * bit assignment in pos[].  This might get cumbersome if there
111
 * are more than a few cards (I only know of 2 at this point).
112
 */
113
 
114
#define MCA_53C710_IDS { 0x01bb, 0x01ba, 0x004f }
115
 
116
/* CARD ID 01BB and 01BA use the same pos values */
117
 
118
#define MCA_01BB_IO_PORTS { 0x0000, 0x0000, 0x0800, 0x0C00, 0x1000, 0x1400, \
119
                            0x1800, 0x1C00, 0x2000, 0x2400, 0x2800, \
120
                            0x2C00, 0x3000, 0x3400, 0x3800, 0x3C00, \
121
                            0x4000, 0x4400, 0x4800, 0x4C00, 0x5000  }
122
 
123
#define MCA_01BB_IRQS { 3, 5, 11, 14 }
124
 
125
/* CARD ID 004f */
126
 
127
#define MCA_004F_IO_PORTS { 0x0000, 0x0200, 0x0300, 0x0400, 0x0500,  0x0600 }
128
 
129
#define MCA_004F_IRQS { 5, 9, 14 }
130
 
131
#endif
132
 
133
#include "scsi.h"
134
#include "hosts.h"
135
#include "sim710.h"
136
 
137
#include<linux/stat.h>
138
 
139
#define DEBUG
140
#undef DEBUG_LIMIT_INTS         /* Define to 10 to hang driver after 10 ints */
141
 
142
/* Debug options available via the "debug:0x1234" parameter             */
143
 
144
#define DEB_NONE        0x0000  /* Nothing                              */
145
#define DEB_HALT        0x0001  /* Detailed trace of chip halt funtion  */
146
#define DEB_REGS        0x0002  /* All chip register read/writes        */
147
#define DEB_SYNC        0x0004  /* Sync/async negotiation               */
148
#define DEB_PMM         0x0008  /* Phase mis-match handling             */
149
#define DEB_INTS        0x0010  /* General interrupt trace              */
150
#define DEB_TOUT        0x0020  /* Selection timeouts                   */
151
#define DEB_RESUME      0x0040  /* Resume addresses for the script      */
152
#define DEB_CMND        0x0080  /* Commands and status returned         */
153
#define DEB_FIXUP       0x0100  /* Fixup of scsi addresses              */
154
#define DEB_DISC        0x0200  /* Disconnect/reselect handling         */
155
 
156
#define DEB_ANY         0xffff  /* Any and all debug options            */
157
 
158
#ifdef DEBUG
159
#define DEB(m,x) if (sim710_debug & m) x
160
int sim710_debug;
161
#else
162
#define DEB(m,x)
163
#endif
164
 
165
/* Redefine scsi_done to force renegotiation of (a)sync transfers
166
 * following any failed command.
167
 */
168
 
169
#define SCSI_DONE(cmd)  { \
170
        DEB(DEB_CMND, printk("scsi%d: Complete %08x\n", \
171
                host->host_no, cmd->result)); \
172
        if (cmd->result) \
173
            hostdata->negotiate |= (1 << cmd->target); \
174
        cmd->scsi_done(cmd); \
175
    }
176
 
177
#ifndef offsetof
178
#define offsetof(t, m)      ((size_t) (&((t *)0)->m))
179
#endif
180
 
181
#define STATE_INITIALISED       0
182
#define STATE_HALTED            1
183
#define STATE_IDLE              2
184
#define STATE_BUSY              3
185
#define STATE_DISABLED          4
186
 
187
#define MAXBOARDS 4     /* Increase this and the sizes of the
188
                           arrays below, if you need more.. */
189
 
190
#ifdef MODULE
191
 
192
char *sim710;           /* command line passed by insmod */
193
 
194
MODULE_AUTHOR("Richard Hirst");
195
MODULE_DESCRIPTION("Simple NCR53C710 driver");
196
MODULE_LICENSE("GPL");
197
 
198
MODULE_PARM(sim710, "s");
199
 
200
#endif
201
 
202
static int sim710_errors;               /* Count of error interrupts */
203
static int sim710_intrs;                /* Count of all interrupts */
204
static int ignore_ids[MAXBOARDS];       /* Accept all SCSI IDs */
205
static int opt_nodisc[MAXBOARDS];       /* Allow disconnect on all IDs */
206
static int opt_noneg[MAXBOARDS];        /* Allow SDTR negotiation on all IDs */
207
static int hostdata_order;              /* Encoded size of hostdata for free_pages() */
208
static int no_of_boards;                /* Actual number of boards/chips */
209
static unsigned int bases[MAXBOARDS];   /* Base addresses of chips */
210
static unsigned int irq_vectors[MAXBOARDS]; /* IRQ vectors used by chips */
211
 
212
/* The SCSI Script!!! */
213
 
214
#include "sim710_d.h"
215
 
216
/* Now define offsets in the DSA, as (A_dsa_xxx/4) */
217
 
218
#define DSA_SELECT      (A_dsa_select/4)
219
#define DSA_MSGOUT      (A_dsa_msgout/4)
220
#define DSA_CMND        (A_dsa_cmnd/4)
221
#define DSA_STATUS      (A_dsa_status/4)
222
#define DSA_MSGIN       (A_dsa_msgin/4)
223
#define DSA_DATAIN      (A_dsa_datain/4)
224
#define DSA_DATAOUT     (A_dsa_dataout/4)
225
#define DSA_SIZE        (A_dsa_size/4)
226
 
227
#define MAX_SG          128     /* Scatter/Gather elements */
228
 
229
#define MAX_MSGOUT      8
230
#define MAX_MSGIN       8
231
#define MAX_CMND        12
232
#define MAX_STATUS      1
233
 
234
struct sim710_hostdata{
235
    int state;
236
    Scsi_Cmnd * issue_queue;
237
    Scsi_Cmnd * running;
238
    int chip;
239
    u8 negotiate;
240
    u8 reselected_identify;
241
    u8 msgin_buf[MAX_MSGIN];
242
    u8 msg_reject;
243
    u32 test1_src __attribute__ ((aligned (4)));
244
    u32 test1_dst;
245
 
246
    struct sim710_target {
247
        Scsi_Cmnd *cur_cmd;
248
        u32 resume_offset;
249
        u32 data_in_jump;
250
        u32 data_out_jump;
251
        u32 dsa[DSA_SIZE];              /* SCSI Script DSA area */
252
        u8  dsa_msgout[MAX_MSGOUT];
253
        u8  dsa_msgin[MAX_MSGIN];
254
        u8  dsa_cdb[MAX_CMND];
255
        u8  dsa_status[MAX_STATUS];
256
    } target[8];
257
 
258
    u32 script[sizeof(SCRIPT)/4] __attribute__ ((aligned (4)));
259
};
260
 
261
 
262
/* Template to request asynchronous transfers */
263
 
264
static const unsigned char async_message[] = {
265
    EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 0, 0 /* asynchronous */};
266
 
267
 
268
static void sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs);
269
static void do_sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs);
270
static __inline__ void run_process_issue_queue(struct sim710_hostdata *);
271
static void process_issue_queue (struct sim710_hostdata *, unsigned long flags);
272
static int full_reset(struct Scsi_Host * host);
273
 
274
 
275
/*
276
 * Function : static void ncr_dump (struct Scsi_Host *host)
277
 *
278
 * Purpose :  Dump (possibly) useful info
279
 *
280
 * Inputs : host - pointer to this host adapter's structure
281
 */
282
 
283
static void
284
ncr_dump (struct Scsi_Host *host)
285
{
286
    unsigned long flags;
287
    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)
288
       host->hostdata[0];
289
 
290
    save_flags(flags);
291
    cli();
292
    printk("scsi%d: Chip register contents:\n", host->host_no);
293
    printk(" (script at virt %p, bus %lx)\n",
294
           hostdata->script, virt_to_bus(hostdata->script));
295
    printk(" 00  sien:  %02x  sdid:  %02x  scntl1:%02x  scntl0:%02x\n"
296
           " 04  socl:  %02x  sodl:  %02x  sxfer: %02x  scid:  %02x\n"
297
           " 08  sbcl:  %02x  sbdl:  %02x  sidl:  %02x  sfbr:  %02x\n"
298
           " 0C  sstat2:%02x  sstat1:%02x  sstat0:%02x  dstat: %02x\n"
299
           " 10  dsa:   %08x\n"
300
           " 14  ctest3:%02x  ctest2:%02x  ctest1:%02x  ctest0:%02x\n"
301
           " 18  ctest7:%02x  ctest6:%02x  ctest5:%02x  ctest4:%02x\n"
302
           " 1C  temp:  %08x\n"
303
           " 20  lcrc:  %02x  ctest8:%02x  istat: %02x  dfifo: %02x\n"
304
           " 24  dbc:   %08x  dnad:  %08x  dsp:   %08x\n"
305
           " 30  dsps:  %08x  scratch:%08x\n"
306
           " 38  dcntl: %02x  dwt:   %02x  dien:  %02x  dmode: %02x\n"
307
           " 3C  adder: %08x\n",
308
          NCR_read8(SIEN_REG), NCR_read8(SDID_REG), NCR_read8(SCNTL1_REG),
309
          NCR_read8(SCNTL0_REG), NCR_read8(SOCL_REG), NCR_read8(SODL_REG),
310
          NCR_read8(SXFER_REG), NCR_read8(SCID_REG), NCR_read8(SBCL_REG),
311
          NCR_read8(SBDL_REG), NCR_read8(SIDL_REG), NCR_read8(SFBR_REG),
312
          NCR_read8(SSTAT2_REG), NCR_read8(SSTAT1_REG), NCR_read8(SSTAT0_REG),
313
          NCR_read8(DSTAT_REG), NCR_read32(DSA_REG), NCR_read8(CTEST3_REG),
314
          NCR_read8(CTEST2_REG), NCR_read8(CTEST1_REG), NCR_read8(CTEST0_REG),
315
          NCR_read8(CTEST7_REG), NCR_read8(CTEST6_REG), NCR_read8(CTEST5_REG),
316
          NCR_read8(CTEST4_REG), NCR_read8(TEMP_REG), NCR_read8(LCRC_REG),
317
          NCR_read8(CTEST8_REG), NCR_read8(ISTAT_REG), NCR_read8(DFIFO_REG),
318
          NCR_read32(DBC_REG), NCR_read32(DNAD_REG), NCR_read32(DSP_REG),
319
          NCR_read32(DSPS_REG), NCR_read32(SCRATCH_REG), NCR_read8(DCNTL_REG),
320
          NCR_read8(DWT_REG), NCR_read8(DIEN_REG), NCR_read8(DMODE_REG),
321
          NCR_read32(ADDER_REG));
322
 
323
    restore_flags(flags);
324
}
325
 
326
 
327
/*
328
 * Function: int param_setup(char *str)
329
 */
330
 
331
__init int
332
param_setup(char *str)
333
{
334
    char *cur = str;
335
    char *p, *pc, *pv;
336
    int val;
337
    int c;
338
 
339
    no_of_boards = 0;
340
    while (no_of_boards < MAXBOARDS && cur != NULL &&
341
                (pc = strchr(cur, ':')) != NULL) {
342
        char *pe;
343
 
344
        val = 0;
345
        pv = pc;
346
        c = *++pv;
347
 
348
        val = (int) simple_strtoul(pv, &pe, 0);
349
 
350
        if (!strncmp(cur, "addr:", 5)) {
351
            bases[no_of_boards++] = val;
352
        }
353
#ifdef DEBUG
354
        else if (!strncmp(cur, "debug:", 6)) {
355
            sim710_debug = val;
356
        }
357
#endif
358
        else if (no_of_boards == 0) {
359
            printk("sim710: Invalid parameters, addr: must come first\n");
360
            no_of_boards = -1;
361
            return 1;
362
        }
363
        else if (!strncmp(cur, "irq:", 4))
364
            irq_vectors[no_of_boards-1] = val;
365
        else if (!strncmp(cur, "ignore:", 7))
366
            ignore_ids[no_of_boards-1] = val;
367
        else if (!strncmp(cur, "nodisc:", 7))
368
            opt_nodisc[no_of_boards-1] = val;
369
        else if (!strncmp(cur, "noneg:", 6))
370
            opt_noneg[no_of_boards-1] = val;
371
        else if (!strncmp(cur, "disabled:", 9)) {
372
            no_of_boards = -1;
373
            return 1;
374
        }
375
        else {
376
            printk("sim710: unexpected boot option '%.*s'\n", (int)(pc-cur+1), cur);
377
            no_of_boards = -1;
378
            return 1;
379
        }
380
 
381
        /* Allow ',', ' ', or '+' seperators.  Used to be ',' at boot and
382
         * ' ' for module load, some installers crap out on the space and
383
         * insmod doesn't like the comma.
384
         */
385
       if ((p = strchr(cur, ',')) || (p = strchr(cur, ' ')) ||
386
               (p = strchr(cur, '+')))
387
           cur = p + 1;
388
        else
389
           break;
390
    }
391
    return 1;
392
}
393
 
394
#ifndef MODULE
395
__setup("sim710=", param_setup);
396
#endif
397
 
398
 
399
/*
400
 * Function: static const char *sbcl_to_phase (int sbcl)
401
 */
402
 
403
static const char *
404
sbcl_to_phase (int sbcl) {
405
    switch (sbcl & SBCL_PHASE_MASK) {
406
    case SBCL_PHASE_DATAIN:
407
        return "DATAIN";
408
    case SBCL_PHASE_DATAOUT:
409
        return "DATAOUT";
410
    case SBCL_PHASE_MSGIN:
411
        return "MSGIN";
412
    case SBCL_PHASE_MSGOUT:
413
        return "MSGOUT";
414
    case SBCL_PHASE_CMDOUT:
415
        return "CMDOUT";
416
    case SBCL_PHASE_STATIN:
417
        return "STATUSIN";
418
    default:
419
        return "unknown";
420
    }
421
}
422
 
423
 
424
/*
425
 * Function : static int ncr_halt (struct Scsi_Host *host)
426
 *
427
 * Purpose : halts the SCSI SCRIPTS(tm) processor on the NCR chip
428
 *
429
 * Inputs : host - SCSI chip to halt
430
 *
431
 * Returns : 0 on success
432
 */
433
 
434
static int
435
ncr_halt (struct Scsi_Host *host)
436
{
437
    unsigned long flags;
438
    unsigned char istat, tmp;
439
    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)
440
        host->hostdata[0];
441
    int stage;
442
    int timeout;
443
    int res = 0;
444
 
445
    save_flags(flags);
446
    cli();
447
    /* Stage 0 : eat all interrupts
448
       Stage 1 : set ABORT
449
       Stage 2 : eat all but abort interrupts
450
       Stage 3 : eat all interrupts
451
       We loop for 50000 times with a delay of 10us which should give us
452
       about half a second.
453
     */
454
    for (stage = 0, timeout = 50000; timeout; timeout--) {
455
        if (stage == 1) {
456
            DEB(DEB_HALT, printk("ncr_halt: writing ISTAT_ABRT\n"));
457
            NCR_write8(ISTAT_REG, ISTAT_ABRT);
458
            ++stage;
459
        }
460
        istat = NCR_read8 (ISTAT_REG);
461
        if (istat & ISTAT_SIP) {
462
            DEB(DEB_HALT, printk("ncr_halt: got ISTAT_SIP, istat=%02x\n", istat));
463
            tmp = NCR_read8(SSTAT0_REG);
464
            DEB(DEB_HALT, printk("ncr_halt: got SSTAT0_REG=%02x\n", tmp));
465
        } else if (istat & ISTAT_DIP) {
466
            DEB(DEB_HALT, printk("ncr_halt: got ISTAT_DIP, istat=%02x\n", istat));
467
            tmp = NCR_read8(DSTAT_REG);
468
            DEB(DEB_HALT, printk("ncr_halt: got DSTAT_REG=%02x\n", tmp));
469
            if (stage == 2) {
470
                if (tmp & DSTAT_ABRT) {
471
                    DEB(DEB_HALT, printk("ncr_halt: got DSTAT_ABRT, clearing istat\n"));
472
                    NCR_write8(ISTAT_REG, 0);
473
                    ++stage;
474
                } else {
475
                    res = 1;
476
                    break;
477
                }
478
            }
479
        }
480
        if (!(istat & (ISTAT_SIP|ISTAT_DIP))) {
481
            if (stage == 0)
482
                ++stage;
483
            else if (stage == 3)
484
                break;
485
        }
486
        udelay(10);
487
    }
488
    restore_flags(flags);
489
 
490
    if (timeout == 0 || res) {
491
        printk(KERN_ALERT "scsi%d: could not halt NCR chip\n", host->host_no);
492
        return 1;
493
    }
494
    else {
495
        hostdata->state = STATE_HALTED;
496
        return 0;
497
    }
498
}
499
 
500
/*
501
 * Function : static void sim710_soft_reset (struct Scsi_Host *host)
502
 *
503
 * Purpose :  perform a soft reset of the NCR53c7xx chip
504
 *
505
 * Inputs : host - pointer to this host adapter's structure
506
 *
507
 * Preconditions : sim710_init must have been called for this
508
 *      host.
509
 *
510
 */
511
 
512
static void
513
sim710_soft_reset (struct Scsi_Host *host)
514
{
515
    unsigned long flags;
516
 
517
    save_flags(flags);
518
    cli();
519
    /*
520
     * Do a soft reset of the chip so that everything is
521
     * reinitialized to the power-on state.
522
     *
523
     * Basically follow the procedure outlined in the NCR53c700
524
     * data manual under Chapter Six, How to Use, Steps Necessary to
525
     * Start SCRIPTS, with the exception of actually starting the
526
     * script and setting up the synchronous transfer gunk.
527
     */
528
 
529
    /* XXX Should we reset the scsi bus here? */
530
 
531
    NCR_write8(SCNTL1_REG, SCNTL1_RST);         /* Reset the bus */
532
    udelay(50);
533
    NCR_write8(SCNTL1_REG, 0);
534
 
535
    udelay(500);
536
 
537
    NCR_write8(ISTAT_REG, ISTAT_10_SRST);       /* Reset the chip */
538
    udelay(50);
539
    NCR_write8(ISTAT_REG, 0);
540
 
541
    mdelay(1000);                               /* Let devices recover */
542
 
543
    NCR_write32(SCRATCH_REG, 0);
544
    NCR_write8(DCNTL_REG, DCNTL_10_COM | DCNTL_700_CF_3);
545
    NCR_write8(CTEST7_REG, CTEST7_10_CDIS|CTEST7_STD);
546
    NCR_write8(DMODE_REG, DMODE_10_BL_8 | DMODE_10_FC2);
547
    NCR_write8(SCID_REG, 1 << host->this_id);
548
    NCR_write8(SBCL_REG, 0);
549
    NCR_write8(SXFER_REG, 0);
550
    NCR_write8(SCNTL1_REG, SCNTL1_ESR_700);
551
    NCR_write8(SCNTL0_REG, SCNTL0_EPC | SCNTL0_EPG_700 | SCNTL0_ARB1 |
552
                SCNTL0_ARB2);
553
 
554
    NCR_write8(DIEN_REG, DIEN_700_BF |
555
                DIEN_ABRT | DIEN_SSI | DIEN_SIR | DIEN_700_OPC);
556
 
557
    NCR_write8(SIEN_REG_700,
558
            SIEN_PAR | SIEN_700_STO | SIEN_RST | SIEN_UDC | SIEN_SGE | SIEN_MA);
559
 
560
    restore_flags(flags);
561
}
562
 
563
 
564
/*
565
 * Function : static void sim710_driver_init (struct Scsi_Host *host)
566
 *
567
 * Purpose : Initialize internal structures, as required on startup, or
568
 *      after a SCSI bus reset.
569
 *
570
 * Inputs : host - pointer to this host adapter's structure
571
 */
572
 
573
static void
574
sim710_driver_init (struct Scsi_Host *host)
575
{
576
    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)
577
        host->hostdata[0];
578
    int i;
579
 
580
    hostdata->running = NULL;
581
    memcpy (hostdata->script, SCRIPT, sizeof(SCRIPT));
582
    for (i = 0; i < PATCHES; i++)
583
        hostdata->script[LABELPATCHES[i]] += virt_to_bus(hostdata->script);
584
    patch_abs_32 (hostdata->script, 0, reselected_identify,
585
        virt_to_bus((void *)&(hostdata->reselected_identify)));
586
    patch_abs_32 (hostdata->script, 0, msgin_buf,
587
        virt_to_bus((void *)&(hostdata->msgin_buf[0])));
588
    patch_abs_32 (hostdata->script, 0, msg_reject,
589
        virt_to_bus((void *)&(hostdata->msg_reject)));
590
    patch_abs_32 (hostdata->script, 0, test1_src,
591
        virt_to_bus((void *)&(hostdata->test1_src)));
592
    patch_abs_32 (hostdata->script, 0, test1_dst,
593
        virt_to_bus((void *)&(hostdata->test1_dst)));
594
    hostdata->state = STATE_INITIALISED;
595
    hostdata->negotiate = 0xff;
596
}
597
 
598
 
599
/* Handle incoming Synchronous data transfer request.  If our negotiate
600
 * flag is set then this is a response to our request, otherwise it is
601
 * spurious request from the target.  Don't really expect target initiated
602
 * SDTRs, because we always negotiate on the first command.  Could still
603
 * get them though..
604
 * The chip is currently paused with ACK asserted on the last byte of the
605
 * SDTR.
606
 * resa is the resume address if the message is in response to our outgoing
607
 * SDTR.  Only possible on initial identify.
608
 * resb is the resume address if the message exchange is initiated by the
609
 * target.
610
 */
611
 
612
static u32
613
handle_sdtr (struct Scsi_Host * host, Scsi_Cmnd * cmd, u32 resa, u32 resb)
614
{
615
    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)host->hostdata[0];
616
    struct sim710_target *targdata = hostdata->target + cmd->target;
617
    u32 resume_offset;
618
 
619
    if (resa && hostdata->negotiate & (1 << cmd->target)) {
620
        DEB(DEB_SYNC, printk("scsi%d: Response to host SDTR = %02x %02x\n",
621
                host->host_no, hostdata->msgin_buf[3], hostdata->msgin_buf[4]));
622
        /* We always issue an SDTR with the identify, so we must issue
623
         * the CDB next.
624
         */
625
        resume_offset = resa;
626
        hostdata->negotiate &= ~(1 << cmd->target);
627
    }
628
    else {
629
        DEB(DEB_SYNC, printk("scsi%d: Target initiated SDTR = %02x %02x\n",
630
                host->host_no, hostdata->msgin_buf[3], hostdata->msgin_buf[4]));
631
        memcpy(targdata->dsa_msgout, async_message, sizeof(async_message));
632
        targdata->dsa[DSA_MSGOUT] = sizeof(async_message);
633
        /* I guess the target could do this anytime; we have to send our
634
         * response, and then continue (sending the CDB if not already done).
635
         */
636
        resume_offset = resb;
637
    }
638
    return resume_offset;
639
}
640
 
641
 
642
/*
643
 * Function : static int datapath_residual (Scsi_Host *host)
644
 *
645
 * Purpose : return residual data count of what's in the chip.
646
 *
647
 * Inputs : host - SCSI host
648
 */
649
 
650
static int
651
datapath_residual (struct Scsi_Host *host) {
652
    int count, synchronous, sstat;
653
    unsigned int ddir;
654
 
655
    count = ((NCR_read8 (DFIFO_REG) & DFIFO_10_BO_MASK) -
656
        (NCR_read32 (DBC_REG) & DFIFO_10_BO_MASK)) & DFIFO_10_BO_MASK;
657
    synchronous = NCR_read8 (SXFER_REG) & SXFER_MO_MASK;
658
    ddir = NCR_read8 (CTEST0_REG_700) & CTEST0_700_DDIR;
659
 
660
    if (ddir) {
661
    /* Receive */
662
        if (synchronous)
663
            count += (NCR_read8 (SSTAT2_REG) & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT;
664
        else
665
            if (NCR_read8 (SSTAT1_REG) & SSTAT1_ILF)
666
                ++count;
667
    } else {
668
    /* Send */
669
        sstat = NCR_read8 (SSTAT1_REG);
670
        if (sstat & SSTAT1_OLF)
671
            ++count;
672
        if (synchronous && (sstat & SSTAT1_ORF))
673
            ++count;
674
    }
675
    return count;
676
}
677
 
678
 
679
static u32
680
handle_idd (struct Scsi_Host * host, Scsi_Cmnd * cmd)
681
{
682
    struct sim710_hostdata *hostdata =
683
                (struct sim710_hostdata *)host->hostdata[0];
684
    struct sim710_target *targdata = hostdata->target + cmd->target;
685
    u32 resume_offset = 0, index;
686
 
687
    index = (u32)((u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script);
688
 
689
    switch (index) {
690
    case Ent_wait_disc_complete/4 + 2:
691
        cmd->result = targdata->dsa_status[0];
692
        SCSI_DONE(cmd);
693
        targdata->cur_cmd = NULL;
694
        resume_offset = Ent_reselect;
695
        break;
696
    case Ent_wait_disc2/4 + 2:
697
        /* Disconnect after command - just wait for a reselect */
698
        targdata->resume_offset = Ent_resume_msgin2a;
699
        resume_offset = Ent_reselect;
700
        break;
701
    case Ent_wait_disc3/4 + 2:
702
        /* Disconnect after the data phase */
703
        targdata->resume_offset = Ent_resume_msgin3a;
704
        resume_offset = Ent_reselect;
705
        break;
706
    case Ent_wait_disc1/4 + 2:
707
        /* Disconnect before command - not expected */
708
        targdata->resume_offset = Ent_resume_msgin1a;
709
        resume_offset = Ent_reselect;
710
        break;
711
    default:
712
        printk("scsi%d: Unexpected Illegal Instruction, script[%04x]\n",
713
                host->host_no, index);
714
        sim710_errors++;
715
        /* resume_offset is zero, which will cause host reset */
716
    }
717
    return resume_offset;
718
}
719
 
720
 
721
/* Handle a phase mismatch.
722
 */
723
 
724
static u32
725
handle_phase_mismatch (struct Scsi_Host * host, Scsi_Cmnd * cmd)
726
{
727
    struct sim710_hostdata *hostdata =
728
                (struct sim710_hostdata *)host->hostdata[0];
729
    struct sim710_target *targdata = hostdata->target + cmd->target;
730
    u32 resume_offset = 0, index;
731
    unsigned char sbcl;
732
 
733
    sbcl = NCR_read8(SBCL_REG) & SBCL_PHASE_MASK;
734
    index = (u32)((u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script);
735
 
736
    DEB(DEB_PMM, printk("scsi%d: Phase mismatch, phase %s (%x) at script[0x%x]\n",
737
        host->host_no, sbcl_to_phase(sbcl), sbcl, index));
738
    DEB(DEB_PMM, print_command(cmd->cmnd));
739
 
740
    if (index == Ent_done_ident/4) {
741
        /* Sending initial message out - probably rejecting our sync
742
         * negotiation request.
743
         */
744
        NCR_write8(SOCL_REG, 0); /* Negate ATN */
745
        if (sbcl == SBCL_PHASE_MSGIN)
746
            resume_offset = Ent_resume_rej_ident;
747
        else if (sbcl == SBCL_PHASE_CMDOUT) {
748
            /* Some old devices (SQ555) switch to cmdout after the first
749
             * byte of an identify message, regardless of whether we
750
             * have more bytes to send!
751
             */
752
            printk("scsi%d: Unexpected switch to CMDOUT during IDENTIFY\n",
753
                host->host_no);
754
            resume_offset = Ent_resume_cmd;
755
        }
756
        else if (sbcl == SBCL_PHASE_STATIN) {
757
            /* Some devices do this on parity error, at least */
758
            printk("scsi%d: Unexpected switch to STATUSIN on initial message out\n",
759
                host->host_no);
760
            resume_offset = Ent_end_data_trans;
761
        }
762
        else {
763
            printk("scsi%d: Unexpected phase change to %s on initial msgout\n",
764
                host->host_no, sbcl_to_phase(sbcl));
765
            /* resume_offset is zero, which will cause a host reset */
766
        }
767
        hostdata->negotiate &= ~(1 << cmd->target);
768
    }
769
    else if (index > Ent_patch_input_data/4 &&
770
                index < Ent_patch_output_data/4) {
771
        /* DataIn transfer phase */
772
        u32 sg_id, oaddr, olen, naddr, nlen;
773
        int residual;
774
 
775
        sg_id = (index - Ent_patch_input_data/4 - 4) / 2;
776
        targdata->data_in_jump = hostdata->script[Ent_patch_input_data/4+1] =
777
                virt_to_bus(hostdata->script + Ent_patch_input_data/4 + sg_id * 2 + 2);
778
        olen  = targdata->dsa[DSA_DATAIN + sg_id * 2];
779
        oaddr = targdata->dsa[DSA_DATAIN + sg_id * 2 + 1];
780
        residual = datapath_residual (host);
781
        if (residual)
782
            printk("scsi%d: Residual count %d on DataIn - NOT expected!!!",
783
                host->host_no, residual);
784
        naddr = NCR_read32(DNAD_REG) - residual;
785
        nlen  = (NCR_read32(DBC_REG) & 0x00ffffff) + residual;
786
        DEB(DEB_PMM, printk("scsi%d: DIN sg %d, old %08x/%08x, new %08x/%08x (%d)\n",
787
                host->host_no, sg_id, oaddr, olen, naddr, nlen, residual));
788
        if (oaddr+olen != naddr+nlen) {
789
            printk("scsi%d: PMM DIN counts error: 0x%x + 0x%x != 0x%x + 0x%x",
790
                host->host_no, oaddr, olen, naddr, nlen);
791
        }
792
        else {
793
            targdata->dsa[DSA_DATAIN + sg_id * 2]     = nlen;
794
            targdata->dsa[DSA_DATAIN + sg_id * 2 + 1] = naddr;
795
            resume_offset = Ent_resume_pmm;
796
        }
797
    }
798
    else if (index > Ent_patch_output_data/4 &&
799
                index <= Ent_end_data_trans/4) {
800
        /* Dataout transfer phase */
801
        u32 sg_id, oaddr, olen, naddr, nlen;
802
        int residual;
803
 
804
        sg_id = (index - Ent_patch_output_data/4 - 4) / 2;
805
        targdata->data_out_jump = hostdata->script[Ent_patch_output_data/4+1] =
806
                virt_to_bus(hostdata->script + Ent_patch_output_data/4 + sg_id * 2 + 2);
807
        olen  = targdata->dsa[DSA_DATAOUT + sg_id * 2];
808
        oaddr = targdata->dsa[DSA_DATAOUT + sg_id * 2 + 1];
809
        residual = datapath_residual (host);
810
        naddr = NCR_read32(DNAD_REG) - residual;
811
        nlen  = (NCR_read32(DBC_REG) & 0x00ffffff) + residual;
812
        DEB(DEB_PMM, printk("scsi%d: DOUT sg %d, old %08x/%08x, new %08x/%08x (%d)\n",
813
                host->host_no, sg_id, oaddr, olen, naddr, nlen, residual));
814
        if (oaddr+olen != naddr+nlen) {
815
            printk("scsi%d: PMM DOUT counts error: 0x%x + 0x%x != 0x%x + 0x%x",
816
                host->host_no, oaddr, olen, naddr, nlen);
817
        }
818
        else {
819
            targdata->dsa[DSA_DATAOUT + sg_id * 2]     = nlen;
820
            targdata->dsa[DSA_DATAOUT + sg_id * 2 + 1] = naddr;
821
            resume_offset = Ent_resume_pmm;
822
        }
823
    }
824
    else if (sbcl == SBCL_PHASE_STATIN) {
825
        /* Change to Status In at some random point; probably wants to report a
826
         * parity error or similar.
827
         */
828
        printk("scsi%d: Unexpected phase change to STATUSIN at index 0x%x\n",
829
                host->host_no, index);
830
        resume_offset = Ent_end_data_trans;
831
    }
832
    else {
833
        printk("scsi%d: Unexpected phase change to %s at index 0x%x\n",
834
                host->host_no, sbcl_to_phase(sbcl), index);
835
        /* resume_offset is zero, which will cause a host reset */
836
    }
837
    /* Flush DMA FIFO */
838
    NCR_write8 (CTEST8_REG, CTEST8_10_CLF);
839
    while (NCR_read8 (CTEST8_REG) & CTEST8_10_CLF);
840
 
841
    return resume_offset;
842
}
843
 
844
 
845
static u32
846
handle_script_int(struct Scsi_Host * host, Scsi_Cmnd * cmd)
847
{
848
    struct sim710_hostdata *hostdata =
849
                (struct sim710_hostdata *)host->hostdata[0];
850
    struct sim710_target *targdata = hostdata->target + cmd->target;
851
    u32 dsps, resume_offset = 0;
852
    unsigned char sbcl;
853
 
854
    dsps = NCR_read32(DSPS_REG);
855
 
856
    switch (dsps) {
857
    case A_int_cmd_complete:
858
        cmd->result = targdata->dsa_status[0];
859
        SCSI_DONE(cmd);
860
        targdata->cur_cmd = NULL;
861
        resume_offset = Ent_reselect;
862
        break;
863
    case A_int_msg_sdtr1:
864
        resume_offset = handle_sdtr(host, cmd,
865
                Ent_resume_msgin1a, Ent_resume_msgin1b);
866
        break;
867
    case A_int_msg_sdtr2:
868
        resume_offset = handle_sdtr(host, cmd, 0, Ent_resume_msgin2b);
869
        break;
870
    case A_int_msg_sdtr3:
871
        resume_offset = handle_sdtr(host, cmd, 0, Ent_resume_msgin3b);
872
        break;
873
    case A_int_disc1:
874
        /* Disconnect before command - not expected */
875
        targdata->resume_offset = Ent_resume_msgin1a;
876
        resume_offset = Ent_reselect;
877
        break;
878
    case A_int_disc2:
879
        /* Disconnect after command - just wait for a reselect */
880
        targdata->resume_offset = Ent_resume_msgin2a;
881
        resume_offset = Ent_reselect;
882
        break;
883
    case A_int_disc3:
884
        /* Disconnect after the data phase */
885
        targdata->resume_offset = Ent_resume_msgin3a;
886
        resume_offset = Ent_reselect;
887
        break;
888
    case A_int_reselected:
889
        hostdata->script[Ent_patch_output_data/4+1] = targdata->data_out_jump;
890
        hostdata->script[Ent_patch_input_data/4+1] = targdata->data_in_jump;
891
        NCR_write32(DSA_REG, virt_to_bus(targdata->dsa));
892
        resume_offset = targdata->resume_offset;
893
        break;
894
    case A_int_data_bad_phase:
895
        sbcl = NCR_read8(SBCL_REG) & SBCL_PHASE_MASK;
896
        printk("scsi%d: int_data_bad_phase, phase %s (%x)\n",
897
                host->host_no, sbcl_to_phase(sbcl), sbcl);
898
        break;
899
    case A_int_bad_msg1:
900
    case A_int_bad_msg2:
901
    case A_int_bad_msg3:
902
    case A_int_cmd_bad_phase:
903
    case A_int_no_msgout1:
904
    case A_int_no_msgout2:
905
    case A_int_no_msgout3:
906
    case A_int_not_cmd_complete:
907
    case A_int_sel_no_ident:
908
    case A_int_sel_not_cmd:
909
    case A_int_status_not_msgin:
910
    case A_int_resel_not_msgin:
911
    case A_int_selected:
912
    case A_int_not_rej:
913
    default:
914
        sbcl = NCR_read8(SBCL_REG) & SBCL_PHASE_MASK;
915
        printk("scsi%d: Unimplemented script interrupt: %08x, phase %s\n",
916
                host->host_no, dsps, sbcl_to_phase(sbcl));
917
        sim710_errors++;
918
        /* resume_offset is zero, which will cause a host reset */
919
    }
920
    return resume_offset;
921
}
922
 
923
 
924
/* A quick wrapper for sim710_intr_handle to grab the spin lock */
925
 
926
static void
927
do_sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
928
{
929
    unsigned long flags;
930
 
931
    spin_lock_irqsave(&io_request_lock, flags);
932
    sim710_intr_handle(irq, dev_id, regs);
933
    spin_unlock_irqrestore(&io_request_lock, flags);
934
}
935
 
936
 
937
/* A "high" level interrupt handler */
938
 
939
static void
940
sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
941
{
942
    struct Scsi_Host * host = (struct Scsi_Host *)dev_id;
943
    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)host->hostdata[0];
944
    Scsi_Cmnd * cmd;
945
    unsigned char istat, dstat;
946
    unsigned char sstat0;
947
    u32 scratch, dsps, resume_offset = 0;
948
 
949
    istat = NCR_read8(ISTAT_REG);
950
    if (!(istat & (ISTAT_SIP|ISTAT_DIP)))
951
        return;
952
    else {
953
        sim710_intrs++;
954
        dsps = NCR_read32(DSPS_REG);
955
        hostdata->state = STATE_HALTED;
956
        sstat0 = dstat = 0;
957
        scratch = NCR_read32(SCRATCH_REG);
958
        if (istat & ISTAT_SIP) {
959
            sstat0 = NCR_read8(SSTAT0_REG);
960
        }
961
        if (istat & ISTAT_DIP) {
962
            udelay(10);         /* Some comment somewhere about 10cycles
963
                                 * between accesses to sstat0 and dstat ??? */
964
            dstat = NCR_read8(DSTAT_REG);
965
        }
966
        DEB(DEB_INTS, printk("scsi%d: Int %d, istat %02x, sstat0 %02x "
967
                "dstat %02x, dsp [%04x], scratch %02x\n",
968
            host->host_no, sim710_intrs, istat, sstat0, dstat,
969
            (u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script,
970
            scratch));
971
        if (scratch & 0x100) {
972
            u8 *p = hostdata->msgin_buf;
973
 
974
            DEB(DEB_INTS, printk("  msgin_buf: %02x %02x %02x %02x\n",
975
                        p[0], p[1], p[2], p[3]));
976
        }
977
        if ((dstat & DSTAT_SIR) && dsps == A_int_reselected) {
978
            /* Reselected.  Identify the target from LCRC_REG, and
979
             * update current command.  If we were trying to select
980
             * a device, then that command needs to go back on the
981
             * issue_queue for later.
982
             */
983
            unsigned char lcrc = NCR_read8(LCRC_REG_10);
984
            int id = 0;
985
 
986
            if (!(lcrc & 0x7f)) {
987
                printk("scsi%d: Reselected with LCRC = %02x\n",
988
                        host->host_no, lcrc);
989
                cmd = NULL;
990
            }
991
            else {
992
                while (!(lcrc & 1)) {
993
                    id++;
994
                    lcrc >>= 1;
995
                }
996
                DEB(DEB_DISC, printk("scsi%d: Reselected by ID %d\n",
997
                        host->host_no, id));
998
                if (hostdata->running) {
999
                    /* Clear SIGP */
1000
                    (void)NCR_read8(CTEST2_REG_700);
1001
 
1002
                    DEB(DEB_DISC, printk("scsi%d: Select of %d interrupted "
1003
                                "by reselect from %d (%p)\n",
1004
                                host->host_no, hostdata->running->target,
1005
                                id, hostdata->target[id].cur_cmd));
1006
                    cmd = hostdata->running;
1007
                    hostdata->target[cmd->target].cur_cmd = NULL;
1008
                    cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue;
1009
                    hostdata->issue_queue = cmd;
1010
                }
1011
                cmd = hostdata->running = hostdata->target[id].cur_cmd;
1012
            }
1013
        }
1014
        else
1015
            cmd = hostdata->running;
1016
 
1017
        if (!cmd) {
1018
            printk("scsi%d: No active command!\n", host->host_no);
1019
            printk("scsi%d: Int %d, istat %02x, sstat0 %02x "
1020
                "dstat %02x, dsp [%04x], scratch %02x, dsps %08x\n",
1021
                host->host_no, sim710_intrs, istat, sstat0, dstat,
1022
                (u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script,
1023
                NCR_read32(SCRATCH_REG), dsps);
1024
            /* resume_offset is zero, which will cause a host reset */
1025
        }
1026
        else if (sstat0 & SSTAT0_700_STO) {
1027
            DEB(DEB_TOUT, printk("scsi%d: Selection timeout\n", host->host_no));
1028
            cmd->result = DID_NO_CONNECT << 16;
1029
            SCSI_DONE(cmd);
1030
            hostdata->target[cmd->target].cur_cmd = NULL;
1031
            resume_offset = Ent_reselect;
1032
        }
1033
        else if (sstat0 & (SSTAT0_SGE|SSTAT0_UDC|SSTAT0_RST|SSTAT0_PAR)) {
1034
            printk("scsi%d: Serious error, sstat0 = %02x\n", host->host_no,
1035
                            sstat0);
1036
            sim710_errors++;
1037
            /* resume_offset is zero, which will cause a host reset */
1038
        }
1039
        else if (dstat & (DSTAT_BF|DSTAT_ABRT|DSTAT_SSI|DSTAT_WTD)) {
1040
            printk("scsi%d: Serious error, dstat = %02x\n", host->host_no,
1041
                            dstat);
1042
            sim710_errors++;
1043
            /* resume_offset is zero, which will cause a host reset */
1044
        }
1045
        else if (dstat & DSTAT_SIR)
1046
            resume_offset = handle_script_int(host, cmd);
1047
        else if (sstat0 & SSTAT0_MA)
1048
            resume_offset = handle_phase_mismatch(host, cmd);
1049
        else if (dstat & DSTAT_IID) {
1050
            /* This can be due to a quick reselect while doing a WAIT
1051
             * DISCONNECT.
1052
             */
1053
            resume_offset = handle_idd(host, cmd);
1054
        }
1055
        else {
1056
            sim710_errors++;
1057
            printk("scsi%d: Spurious interrupt!\n", host->host_no);
1058
            /* resume_offset is zero, which will cause a host reset */
1059
        }
1060
    }
1061
 
1062
    if (resume_offset) {
1063
        if (resume_offset == Ent_reselect) {
1064
            hostdata->running = NULL;
1065
            hostdata->state = STATE_IDLE;
1066
        }
1067
        else
1068
            hostdata->state = STATE_BUSY;
1069
        DEB(DEB_RESUME, printk("scsi%d: Resuming at script[0x%x]\n",
1070
                host->host_no, resume_offset/4));
1071
#ifdef DEBUG_LIMIT_INTS
1072
        if (sim710_intrs < DEBUG_LIMIT_INTS)
1073
#endif
1074
        {
1075
            NCR_write32(SCRATCH_REG, 0);
1076
            NCR_write32(DSP_REG, virt_to_bus(hostdata->script+resume_offset/4));
1077
        }
1078
        if (resume_offset == Ent_reselect)
1079
            run_process_issue_queue(hostdata);
1080
    }
1081
    else {
1082
        printk("scsi%d: Failed to handle interrupt.  Failing commands "
1083
                "and resetting SCSI bus and chip\n", host->host_no);
1084
        mdelay(1000);           /* Give chance to read screen!! */
1085
        full_reset(host);
1086
    }
1087
}
1088
 
1089
 
1090
static void
1091
run_command (struct sim710_hostdata *hostdata, Scsi_Cmnd *cmd)
1092
{
1093
    struct Scsi_Host *host = cmd->host;
1094
    struct sim710_target *targdata = hostdata->target + cmd->target;
1095
    int i, datain, dataout, sg_start;
1096
    u32 *dip, *dop, dsa;
1097
 
1098
    DEB(DEB_CMND, printk("scsi%d: id%d starting ", host->host_no,
1099
                cmd->target));
1100
    DEB(DEB_CMND, print_command(cmd->cmnd));
1101
 
1102
    switch (cmd->cmnd[0]) {
1103
    case INQUIRY:
1104
    case MODE_SENSE:
1105
    case READ_6:
1106
    case READ_10:
1107
    case READ_CAPACITY:
1108
    case REQUEST_SENSE:
1109
    case READ_BLOCK_LIMITS:
1110
    case READ_TOC:
1111
        datain = 1;
1112
        dataout = 0;
1113
        break;
1114
    case MODE_SELECT:
1115
    case WRITE_6:
1116
    case WRITE_10:
1117
        datain = 0;
1118
        dataout = 1;
1119
        break;
1120
    case TEST_UNIT_READY:
1121
    case ALLOW_MEDIUM_REMOVAL:
1122
    case START_STOP:
1123
        datain = dataout = 0;
1124
        break;
1125
    default:
1126
        datain = dataout = 1;
1127
    }
1128
 
1129
    memcpy(targdata->dsa_cdb, cmd->cmnd, MAX_CMND);
1130
 
1131
    targdata->dsa_msgout[0] =
1132
                IDENTIFY((opt_nodisc[hostdata->chip] & (1<<cmd->target)) ? 0 : 1 ,0);
1133
    if (hostdata->negotiate & (1 << cmd->target)) {
1134
        if (opt_noneg[hostdata->chip] & (1 << cmd->target)) {
1135
            hostdata->negotiate ^= (1 << cmd->target);
1136
            targdata->dsa[DSA_MSGOUT] = 1;
1137
        }
1138
        else {
1139
            DEB(DEB_SYNC, printk("scsi%d: Negotiating async transfers "
1140
                "for ID %d\n",
1141
                host->host_no, cmd->target));
1142
            memcpy(targdata->dsa_msgout+1, async_message, sizeof(async_message));
1143
            targdata->dsa[DSA_MSGOUT] = sizeof(async_message) + 1;
1144
        }
1145
    }
1146
    else
1147
        targdata->dsa[DSA_MSGOUT] = 1;
1148
 
1149
    targdata->dsa_msgin[0] = 0xff;
1150
    targdata->dsa_status[0] = 0xff;
1151
 
1152
    targdata->dsa[DSA_SELECT]           = (1 << cmd->target) << 16;
1153
    targdata->dsa[DSA_MSGOUT+1]         = virt_to_bus(targdata->dsa_msgout);
1154
    targdata->dsa[DSA_CMND]             = cmd->cmd_len;
1155
    targdata->dsa[DSA_CMND+1]           = virt_to_bus(targdata->dsa_cdb);
1156
    targdata->dsa[DSA_STATUS]           = 1;
1157
    targdata->dsa[DSA_STATUS+1]         = virt_to_bus(targdata->dsa_status);
1158
    targdata->dsa[DSA_MSGIN]            = 1;
1159
    targdata->dsa[DSA_MSGIN+1]          = virt_to_bus(targdata->dsa_msgin);
1160
 
1161
    sg_start = (MAX_SG - (cmd->use_sg ? cmd->use_sg : 1)) * 2;
1162
    dip = targdata->dsa + DSA_DATAIN + sg_start;
1163
    dop = targdata->dsa + DSA_DATAOUT + sg_start;
1164
 
1165
    for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; i++) {
1166
        u32 vbuf = cmd->use_sg ?
1167
                (u32)(((struct scatterlist *)cmd->buffer)[i].address) :
1168
                (u32)(cmd->request_buffer);
1169
        u32 bbuf = virt_to_bus((void *)vbuf);
1170
        u32 cnt = cmd->use_sg ?
1171
                ((struct scatterlist *)cmd->buffer)[i].length :
1172
                cmd->request_bufflen;
1173
 
1174
        if (datain) {
1175
            *dip++      = cnt;
1176
            *dip++      = bbuf;
1177
        }
1178
        if (dataout) {
1179
            *dop++      = cnt;
1180
            *dop++      = bbuf;
1181
        }
1182
    }
1183
    targdata->data_out_jump = hostdata->script[Ent_patch_output_data/4+1] =
1184
        virt_to_bus(hostdata->script + Ent_patch_output_data/4 + sg_start + 2);
1185
    targdata->data_in_jump = hostdata->script[Ent_patch_input_data/4+1] =
1186
        virt_to_bus(hostdata->script + Ent_patch_input_data/4 + sg_start + 2);
1187
 
1188
    for (i = 0, dsa = virt_to_bus(targdata->dsa); i < 4; i++) {
1189
        u32 v = hostdata->script[Ent_patch_new_dsa/4 + i * 2];
1190
 
1191
        v &= ~0x0000ff00;
1192
        v |= (dsa & 0xff) << 8;
1193
        hostdata->script[Ent_patch_new_dsa/4 + i * 2] = v;
1194
        dsa >>= 8;
1195
    }
1196
    hostdata->running = targdata->cur_cmd = cmd;
1197
    hostdata->state = STATE_BUSY;
1198
 
1199
    NCR_write8(ISTAT_REG, ISTAT_10_SIGP);
1200
}
1201
 
1202
 
1203
static volatile int process_issue_queue_running = 0;
1204
 
1205
static __inline__ void
1206
run_process_issue_queue(struct sim710_hostdata *hostdata)
1207
{
1208
    unsigned long flags;
1209
    save_flags (flags);
1210
    cli();
1211
    if (!process_issue_queue_running) {
1212
        process_issue_queue_running = 1;
1213
        process_issue_queue(hostdata, flags);
1214
        /*
1215
         * process_issue_queue_running is cleared in process_issue_queue
1216
         * once it can't do more work, and process_issue_queue exits with
1217
         * interrupts disabled.
1218
         */
1219
    }
1220
    restore_flags (flags);
1221
}
1222
 
1223
 
1224
/*
1225
 * Function : process_issue_queue (hostdata, flags)
1226
 *
1227
 * Purpose : Start next command for any idle target.
1228
 *
1229
 * NOTE : process_issue_queue exits with interrupts *disabled*, so the
1230
 *      caller must reenable them if it desires.
1231
 *
1232
 * NOTE : process_issue_queue should be called from both
1233
 *      sim710_queue_command() and from the interrupt handler
1234
 *      after command completion.
1235
 */
1236
 
1237
static void
1238
process_issue_queue (struct sim710_hostdata *hostdata, unsigned long flags)
1239
{
1240
    Scsi_Cmnd *tmp, *prev;
1241
    int done;
1242
 
1243
    /*
1244
     * We run (with interrupts disabled) until we're sure that none of
1245
     * the host adapters have anything that can be done, at which point
1246
     * we set process_issue_queue_running to 0 and exit.
1247
     *
1248
     * Interrupts are enabled before doing various other internal
1249
     * instructions, after we've decided that we need to run through
1250
     * the loop again.
1251
     *
1252
     */
1253
 
1254
    do {
1255
        cli(); /* Freeze request queues */
1256
        done = 1;
1257
        if (hostdata->issue_queue) {
1258
            if (hostdata->state == STATE_DISABLED) {
1259
                tmp = (Scsi_Cmnd *) hostdata->issue_queue;
1260
                hostdata->issue_queue = (Scsi_Cmnd *) tmp->SCp.ptr;
1261
                tmp->result = (DID_BAD_TARGET << 16);
1262
                tmp->scsi_done (tmp);
1263
                done = 0;
1264
            }
1265
            else if (hostdata->state == STATE_IDLE) {
1266
                for (tmp = hostdata->issue_queue, prev = NULL; tmp;
1267
                                prev = tmp, tmp = (Scsi_Cmnd *) tmp->SCp.ptr) {
1268
                    if (hostdata->target[tmp->target].cur_cmd == NULL) {
1269
                        if (prev)
1270
                            prev->SCp.ptr = tmp->SCp.ptr;
1271
                        else
1272
                            hostdata->issue_queue = (Scsi_Cmnd *) tmp->SCp.ptr;
1273
                        tmp->SCp.ptr = NULL;
1274
                        run_command (hostdata, tmp);
1275
                        done = 0;
1276
                    } /* if target/lun is not busy */
1277
                } /* scan issue queue for work */
1278
            } /* host is idle */
1279
        } /* if hostdata->issue_queue */
1280
        if (!done)
1281
            restore_flags (flags);
1282
    } while (!done);
1283
    process_issue_queue_running = 0;
1284
}
1285
 
1286
 
1287
int
1288
sim710_queuecommand(Scsi_Cmnd * cmd, void (*done)(Scsi_Cmnd *))
1289
{
1290
    struct Scsi_Host *host = cmd->host;
1291
    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)host->hostdata[0];
1292
    Scsi_Cmnd *tmp;
1293
    unsigned long flags;
1294
 
1295
    if (cmd->lun) {
1296
        /* Silently ignore luns other than zero! */
1297
        cmd->result = (DID_BAD_TARGET << 16);
1298
        done(cmd);
1299
        return 0;
1300
    }
1301
 
1302
    DEB(DEB_CMND, printk("scsi%d: id%d queuing ", host->host_no,
1303
                cmd->target));
1304
    DEB(DEB_CMND, print_command(cmd->cmnd));
1305
 
1306
    cmd->scsi_done = done;
1307
    cmd->host_scribble = NULL;
1308
    cmd->SCp.ptr = NULL;
1309
    cmd->SCp.buffer = NULL;
1310
 
1311
    save_flags(flags);
1312
    cli();
1313
 
1314
    if (ignore_ids[hostdata->chip] & (1 << cmd->target)) {
1315
        printk("scsi%d: ignoring target %d\n", host->host_no, cmd->target);
1316
        cmd->result = (DID_BAD_TARGET << 16);
1317
        done(cmd);
1318
        restore_flags (flags);
1319
        return 0;
1320
    }
1321
#ifdef DEBUG_LIMIT_INTS
1322
    if (sim710_intrs > DEBUG_LIMIT_INTS) {
1323
        cmd->result = (DID_BAD_TARGET << 16);
1324
        done(cmd);
1325
        restore_flags (flags);
1326
        return 0;
1327
    }
1328
#endif
1329
    if (cmd->use_sg > MAX_SG)
1330
        panic ("cmd->use_sg = %d\n", cmd->use_sg);
1331
 
1332
    if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
1333
        cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue;
1334
        hostdata->issue_queue = cmd;
1335
    } else {
1336
        for (tmp = hostdata->issue_queue; tmp->SCp.ptr;
1337
                tmp = (Scsi_Cmnd *) tmp->SCp.ptr);
1338
        tmp->SCp.ptr = (unsigned char *) cmd;
1339
    }
1340
    restore_flags (flags);
1341
    run_process_issue_queue(hostdata);
1342
    return 0;
1343
}
1344
 
1345
 
1346
__init int
1347
sim710_detect(Scsi_Host_Template * tpnt)
1348
{
1349
    unsigned char scsi_id;
1350
    unsigned int base_addr;
1351
    struct Scsi_Host * host = NULL;
1352
    struct sim710_hostdata *hostdata;
1353
    unsigned long timeout;
1354
    unsigned long irq_mask;
1355
    int requested_irq;
1356
    int probed_irq;
1357
    u32 dsps;
1358
    int chips = 0;
1359
    int limit;
1360
    int indx;
1361
    int revision;
1362
    int size;
1363
    volatile u8 tmp;
1364
    struct Scsi_Host *our_hosts[MAXBOARDS+1];
1365
 
1366
#ifdef MODULE
1367
    if (sim710)
1368
        param_setup(sim710);
1369
#endif
1370
 
1371
    if (no_of_boards < 0) {
1372
        printk("sim710: NCR53C710 driver disabled\n");
1373
        return 0;
1374
    }
1375
 
1376
#ifdef CONFIG_MCA
1377
    /* If board details have been specified via boot/module parameters,
1378
     * then don't bother probing.
1379
     */
1380
    if (no_of_boards == 0) {
1381
        int slot;
1382
        int pos[3];
1383
        int mca_53c710_ids[] = MCA_53C710_IDS;
1384
        int *id_to_check = mca_53c710_ids;
1385
        static int io_004f_by_pos[] = MCA_004F_IO_PORTS;
1386
        static int irq_004f_by_pos[] = MCA_004F_IRQS;
1387
        static int io_01bb_by_pos[] = MCA_01BB_IO_PORTS;
1388
        static int irq_01bb_by_pos[] = MCA_01BB_IRQS;
1389
 
1390
        while ( *id_to_check && no_of_boards < MAXBOARDS) {
1391
            if (!MCA_bus)
1392
                return 0;
1393
 
1394
            if ((slot = mca_find_adapter(*id_to_check, 0)) != MCA_NOTFOUND) {
1395
 
1396
                pos[0] = mca_read_stored_pos(slot, 2);
1397
                pos[1] = mca_read_stored_pos(slot, 3);
1398
                pos[2] = mca_read_stored_pos(slot, 4);
1399
 
1400
                /*
1401
                 * 01BB & 01BA port base by bits 7,6,5,4,3,2 in pos[2]
1402
                 *
1403
                 *    000000  <disabled>   001010  0x2800
1404
                 *    000001  <invalid>    001011  0x2C00
1405
                 *    000010  0x0800       001100  0x3000
1406
                 *    000011  0x0C00       001101  0x3400
1407
                 *    000100  0x1000       001110  0x3800
1408
                 *    000101  0x1400       001111  0x3C00
1409
                 *    000110  0x1800       010000  0x4000
1410
                 *    000111  0x1C00       010001  0x4400
1411
                 *    001000  0x2000       010010  0x4800
1412
                 *    001001  0x2400       010011  0x4C00
1413
                 *                         010100  0x5000
1414
                 *
1415
                 * 00F4 port base by bits 3,2,1 in pos[0]
1416
                 *
1417
                 *    000  <disabled>      001    0x200
1418
                 *    010  0x300           011    0x400
1419
                 *    100  0x500           101    0x600
1420
                 *
1421
                 * 01BB & 01BA IRQ is specified in pos[0] bits 7 and 6:
1422
                 *
1423
                 *    00   3               10   11
1424
                 *    01   5               11   14
1425
                 *
1426
                 * 00F4 IRQ specified by bits 6,5,4 in pos[0]
1427
                 *
1428
                 *    100   5              101    9
1429
                 *    110   14
1430
                 */
1431
 
1432
                if ( *id_to_check == 0x01bb || *id_to_check == 0x01ba ) {
1433
                    bases[no_of_boards] = io_01bb_by_pos[(pos[2] & 0xFC) >> 2];
1434
                    irq_vectors[no_of_boards] =
1435
                                irq_01bb_by_pos[((pos[0] & 0xC0) >> 6)];
1436
                    if (bases[no_of_boards] == 0x0000)
1437
                        printk("sim710: NCR53C710 Adapter ID 0x01bb is disabled.\n");
1438
                    else {
1439
                        no_of_boards++;
1440
                        if ( *id_to_check == 0x01bb )
1441
                            mca_set_adapter_name( slot,
1442
                                    "NCR 3360/3430 SCSI SubSystem" );
1443
                        else
1444
                            mca_set_adapter_name(slot,
1445
                                    "NCR Dual SIOP SCSI Host Adapter Board");
1446
                    }
1447
                }
1448
                else if ( *id_to_check == 0x004f ) {
1449
                    bases[no_of_boards] = io_004f_by_pos[((pos[0] & 0x0E) >> 1)];
1450
                    irq_vectors[no_of_boards] =
1451
                                irq_004f_by_pos[((pos[0] & 0x70) >> 4) - 4];
1452
                    if (bases[no_of_boards] == 0x0000)
1453
                        printk("sim710: NCR53C710 Adapter ID 0x004f is disabled.\n");
1454
                    else {
1455
                        no_of_boards++;
1456
                        mca_set_adapter_name(slot,
1457
                                "NCR 53c710 SCSI Host Adapter Board");
1458
                    }
1459
                }
1460
            }
1461
            id_to_check++;
1462
        }
1463
    }
1464
#endif
1465
 
1466
#ifdef CONFIG_EISA
1467
    /* Auto probe, if no boards specified in boot parameters */
1468
    if (no_of_boards == 0) {
1469
        int io_addr;
1470
        /* reverse probe, so my on-board controller at 0x9000 is always scsi0 */
1471
        for (io_addr = 0x9000; no_of_boards < MAXBOARDS && io_addr >= 0x1000; io_addr -= 0x1000) {
1472
            if (request_region(io_addr, 0x40, "sim710") != NULL) {
1473
                int id0 = inw(io_addr + 0xc80);
1474
                int id1 = inw(io_addr + 0xc82);
1475
                /* The on-board controller on my Proliant 2000 is 0x1044,
1476
                 * my EISA card is 0x1144.
1477
                 */
1478
                if (id0 == 0x110e && (id1 == 0x1044 || id1 == 0x1144)) {
1479
                    bases[no_of_boards] = io_addr;
1480
#if 0
1481
                    /* This should detect the IRQ, but I havn't proved it for
1482
                     * myself.  Leave the old probe code active for now, as
1483
                     * no-one has reported problems with it.
1484
                     */
1485
                    switch (inb(io_addr + 0xc88)) {
1486
                        case (0x00):
1487
                            irq_vectors[no_of_boards] = 11;
1488
                            break;
1489
                        case (0x01):
1490
                            irq_vectors[no_of_boards] = 14;
1491
                            break;
1492
                        case (0x02):
1493
                            irq_vectors[no_of_boards] = 15;
1494
                            break;
1495
                        case (0x03):
1496
                            irq_vectors[no_of_boards] = 10;
1497
                            break;
1498
                        case (0x04):
1499
                            irq_vectors[no_of_boards] = 9;
1500
                            break;
1501
                        default:
1502
                            printk("sim710.c: irq nasty\n");
1503
                    }
1504
#endif
1505
                    no_of_boards++;
1506
                }
1507
                release_region(io_addr, 64);
1508
            }
1509
        }
1510
    }
1511
#endif
1512
    if (!no_of_boards) {
1513
        printk("sim710: No NCR53C710 adapter found.\n");
1514
        return 0;
1515
    }
1516
 
1517
    size = sizeof(struct sim710_hostdata);
1518
    hostdata_order = 0;
1519
    while (size > (PAGE_SIZE << hostdata_order))
1520
        hostdata_order++;
1521
    size = PAGE_SIZE << hostdata_order;
1522
 
1523
    DEB(DEB_ANY, printk("sim710: hostdata %d bytes, size %d, order %d\n",
1524
        sizeof(struct sim710_hostdata), size, hostdata_order));
1525
 
1526
    tpnt->proc_name = "sim710";
1527
 
1528
    memset(our_hosts, 0, sizeof(our_hosts));
1529
    for (indx = 0; indx < no_of_boards; indx++) {
1530
        unsigned long page = __get_free_pages(GFP_ATOMIC, hostdata_order);
1531
        if(page == 0UL)
1532
        {
1533
            printk(KERN_WARNING "sim710: out of memory registering board %d.\n", indx);
1534
            break;
1535
        }
1536
        host = scsi_register(tpnt, 4);
1537
        if(host == NULL) {
1538
            free_pages(host->hostdata[0], hostdata_order);
1539
            break;
1540
        }
1541
        our_hosts[chips] = host;
1542
        host->hostdata[0] = page;
1543
        hostdata = (struct sim710_hostdata *)host->hostdata[0];
1544
        memset(hostdata, 0, size);
1545
        scsi_id = 7;
1546
        base_addr = bases[indx];
1547
        requested_irq = irq_vectors[indx];
1548
        printk("scsi%d: Configuring Sim710 (SCSI-ID %d) at %x, IRQ %d\n",
1549
                        host->host_no, scsi_id, base_addr, requested_irq);
1550
        DEB(DEB_ANY, printk("sim710: hostdata = %p (%d bytes), dsa0 = %p\n",
1551
                        hostdata, sizeof(struct sim710_hostdata),
1552
                         hostdata->target[0].dsa));
1553
        hostdata->chip = indx;
1554
        host->irq = requested_irq;
1555
        host->this_id = scsi_id;
1556
        host->unique_id = base_addr;
1557
        host->base = base_addr;
1558
        hostdata->msg_reject = MESSAGE_REJECT;
1559
 
1560
        if (ncr_halt(host)) {
1561
            free_pages(host->hostdata[0], hostdata_order);
1562
            scsi_unregister (host);
1563
            printk("scsi%d: Failed to initialise 53c710 at address %x\n",
1564
                        host->host_no, base_addr);
1565
            continue;
1566
        }
1567
        DEB(DEB_ANY,ncr_dump(host));
1568
        revision = (NCR_read8(CTEST8_REG) & 0xF0) >> 4;
1569
        printk("scsi%d: Revision 0x%x\n",host->host_no,revision);
1570
        sim710_soft_reset(host);
1571
 
1572
        sim710_driver_init(host);
1573
 
1574
        request_region((u32)host->base, 64, "sim710");
1575
        /* Now run test1 */
1576
        hostdata->test1_src = 0x53c710aa;
1577
        hostdata->test1_dst = 0x76543210;
1578
        NCR_write32(DSPS_REG, 0x89abcdef);
1579
        irq_mask = probe_irq_on();
1580
        NCR_write32(DSP_REG, virt_to_bus(hostdata->script+Ent_test1/4));
1581
        timeout = 5;
1582
        while (hostdata->test1_dst != hostdata->test1_src && timeout--)
1583
            mdelay(100);
1584
        tmp = NCR_read8(ISTAT_REG);
1585
        tmp = NCR_read8(SSTAT0_REG);
1586
        udelay(10);
1587
        tmp = NCR_read8(DSTAT_REG);
1588
        probed_irq = probe_irq_off(irq_mask);
1589
        if (requested_irq == 0) {
1590
            if (probed_irq > 0) {
1591
                printk("scsi%d: Chip is using IRQ %d\n", host->host_no,
1592
                        probed_irq);
1593
                requested_irq = host->irq = probed_irq;
1594
            }
1595
            else {
1596
                printk("scsi%d: Failed to probe for IRQ (returned %d)\n",
1597
                        host->host_no, probed_irq);
1598
                ncr_halt(host);
1599
                free_pages(host->hostdata[0], hostdata_order);
1600
                scsi_unregister (host);
1601
                release_region((u32)host->base, 64);
1602
                continue;
1603
            }
1604
        }
1605
        else if (probed_irq > 0 && probed_irq != requested_irq)
1606
            printk("scsi%d: WARNING requested IRQ %d, but probed as %d\n",
1607
                        host->host_no, requested_irq, probed_irq);
1608
        else if (probed_irq <= 0)
1609
            printk("scsi%d: WARNING IRQ probe failed, (returned %d)\n",
1610
                        host->host_no, probed_irq);
1611
 
1612
        dsps = NCR_read32(DSPS_REG);
1613
        if (hostdata->test1_dst != 0x53c710aa || dsps != A_int_test1) {
1614
            if (hostdata->test1_dst != 0x53c710aa)
1615
                printk("scsi%d: test 1 FAILED: data: exp 0x53c710aa, got 0x%08x\n",
1616
                        host->host_no, hostdata->test1_dst);
1617
            if (dsps != A_int_test1)
1618
                printk("scsi%d: test 1 FAILED: dsps: exp 0x%08x, got 0x%08x\n",
1619
                        host->host_no, A_int_test1, dsps);
1620
            ncr_dump(host);
1621
            ncr_halt(host);
1622
            free_pages(host->hostdata[0], hostdata_order);
1623
            scsi_unregister (host);
1624
            release_region((u32)host->base, 64);
1625
            continue;
1626
        }
1627
        printk("scsi%d: test 1 completed ok.\n", host->host_no);
1628
 
1629
        NCR_write32(DSP_REG, virt_to_bus(hostdata->script+Ent_reselect/4));
1630
        hostdata->state = STATE_IDLE;
1631
        chips++;
1632
    }
1633
    /* OK, now run down our_hosts[] calling request_irq(... SA_SHIRQ ...).
1634
     * Couldn't call request_irq earlier, as probing would have failed.
1635
     */
1636
    for (indx = 0, limit = chips; indx < limit; indx++) {
1637
        host = our_hosts[indx];
1638
        if (request_irq(host->irq, do_sim710_intr_handle,
1639
                       SA_INTERRUPT | SA_SHIRQ, "sim710", host))
1640
        {
1641
            printk("scsi%d : IRQ%d not free, detaching\n",
1642
                        host->host_no, host->irq);
1643
            ncr_halt(host);
1644
            free_pages(host->hostdata[0], hostdata_order);
1645
            scsi_unregister (host);
1646
            chips--;
1647
        }
1648
    }
1649
 
1650
    return chips;
1651
}
1652
 
1653
int
1654
sim710_abort(Scsi_Cmnd * cmd)
1655
{
1656
    struct Scsi_Host * host = cmd->host;
1657
 
1658
    printk("scsi%d: Unable to abort command for target %d\n",
1659
           host->host_no, cmd->target);
1660
    return FAILED;
1661
}
1662
 
1663
/*
1664
 * This is a device reset.  Need to select and send a Bus Device Reset msg.
1665
 */
1666
 
1667
int
1668
sim710_dev_reset(Scsi_Cmnd * SCpnt)
1669
{
1670
    struct Scsi_Host * host = SCpnt->host;
1671
 
1672
    printk("scsi%d: Unable to send Bus Device Reset for target %d\n",
1673
           host->host_no, SCpnt->target);
1674
    return FAILED;
1675
}
1676
 
1677
/*
1678
 * This is bus reset.  We need to reset the bus and fail any active commands.
1679
 */
1680
 
1681
int
1682
sim710_bus_reset(Scsi_Cmnd * SCpnt)
1683
{
1684
    struct Scsi_Host * host = SCpnt->host;
1685
 
1686
    printk("scsi%d: Unable to do SCSI bus reset\n", host->host_no);
1687
    return FAILED;
1688
}
1689
 
1690
static int
1691
full_reset(struct Scsi_Host * host)
1692
{
1693
    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)
1694
            host->hostdata[0];
1695
    int target;
1696
    Scsi_Cmnd *cmd;
1697
    u32 istat, dstat = 0, sstat0 = 0, sstat1 = 0, dsp, dsps, scratch;
1698
    unsigned long flags;
1699
 
1700
    save_flags(flags);
1701
    cli();
1702
 
1703
    istat = NCR_read8(ISTAT_REG);
1704
    if (istat & ISTAT_SIP) {
1705
        sstat0 = NCR_read8(SSTAT0_REG);
1706
        sstat1 = NCR_read8(SSTAT1_REG);
1707
        udelay(10);
1708
    }
1709
    if (istat & ISTAT_DIP)
1710
        dstat = NCR_read8(DSTAT_REG);
1711
 
1712
    if (ncr_halt(host)) {
1713
        restore_flags(flags);
1714
        return FAILED;
1715
    }
1716
    restore_flags(flags);
1717
    dsp = NCR_read32(DSP_REG);
1718
    dsps = NCR_read32(DSPS_REG);
1719
    scratch = NCR_read32(SCRATCH_REG);
1720
    printk("scsi%d: istat = %02x, sstat0 = %02x, sstat1 = %02x, dstat = %02x\n",
1721
                host->host_no, istat, sstat0, sstat1, dstat);
1722
    printk("scsi%d: dsp = %08x (script[0x%04x]), dsps = %08x, scratch = %08x\n",
1723
                host->host_no, dsp,
1724
                ((u32)bus_to_virt(dsp) - (u32)hostdata->script)/4, dsps, scratch);
1725
 
1726
    for (target = 0; target < 7; target++) {
1727
        if ((cmd = hostdata->target[target].cur_cmd)) {
1728
            printk("scsi%d: Failing command for ID%d\n",
1729
                        host->host_no, target);
1730
            cmd->result = DID_RESET << 16;
1731
            cmd->scsi_done(cmd);
1732
            hostdata->target[target].cur_cmd = NULL;
1733
        }
1734
    }
1735
 
1736
    sim710_soft_reset(host);
1737
    sim710_driver_init(host);
1738
 
1739
    NCR_write32(DSP_REG, virt_to_bus(hostdata->script+Ent_reselect/4));
1740
    hostdata->state = STATE_IDLE;
1741
 
1742
    run_process_issue_queue(hostdata);
1743
 
1744
    return SUCCESS;
1745
}
1746
 
1747
/*
1748
 * This is host reset.  We need to reset the chip and the bus.
1749
 */
1750
 
1751
int
1752
sim710_host_reset(Scsi_Cmnd * SCpnt)
1753
{
1754
    struct Scsi_Host * host = SCpnt->host;
1755
 
1756
    printk("scsi%d: >>>>>>>>>>>> Host reset <<<<<<<<<<<<\n", host->host_no);
1757
 
1758
    return full_reset(host);
1759
}
1760
 
1761
#ifdef MODULE
1762
 
1763
int
1764
sim710_release(struct Scsi_Host *host)
1765
{
1766
    ncr_halt(host);
1767
    free_pages(host->hostdata[0], hostdata_order);
1768
    free_irq(host->irq, host);
1769
    release_region((u32)host->base, 64);
1770
    return 1;
1771
}
1772
 
1773
#endif
1774
 
1775
static Scsi_Host_Template driver_template = SIM710_SCSI;
1776
 
1777
#include "scsi_module.c"

powered by: WebSVN 2.1.0

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