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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/*
2
 *      ultrastor.c     Copyright (C) 1992 David B. Gentzel
3
 *      Low-level SCSI driver for UltraStor 14F, 24F, and 34F
4
 *      by David B. Gentzel, Whitfield Software Services, Carnegie, PA
5
 *          (gentzel@nova.enet.dec.com)
6
 *  scatter/gather added by Scott Taylor (n217cg@tamuts.tamu.edu)
7
 *  24F and multiple command support by John F. Carr (jfc@athena.mit.edu)
8
 *    John's work modified by Caleb Epstein (cae@jpmorgan.com) and
9
 *    Eric Youngdale (ericy@cais.com).
10
 *      Thanks to UltraStor for providing the necessary documentation
11
 */
12
 
13
/*
14
 * TODO:
15
 *      1. Find out why scatter/gather is limited to 16 requests per command.
16
 *         This is fixed, at least on the 24F, as of version 1.12 - CAE.
17
 *      2. Look at command linking (mscp.command_link and
18
 *         mscp.command_link_id).  (Does not work with many disks,
19
 *                              and no performance increase.  ERY).
20
 *      3. Allow multiple adapters.
21
 */
22
 
23
/*
24
 * NOTES:
25
 *    The UltraStor 14F, 24F, and 34F are a family of intelligent, high
26
 *    performance SCSI-2 host adapters.  They all support command queueing
27
 *    and scatter/gather I/O.  Some of them can also emulate the standard
28
 *    WD1003 interface for use with OS's which don't support SCSI.  Here
29
 *    is the scoop on the various models:
30
 *      14F - ISA first-party DMA HA with floppy support and WD1003 emulation.
31
 *      14N - ISA HA with floppy support.  I think that this is a non-DMA
32
 *            HA.  Nothing further known.
33
 *      24F - EISA Bus Master HA with floppy support and WD1003 emulation.
34
 *      34F - VL-Bus Bus Master HA with floppy support (no WD1003 emulation).
35
 *
36
 *    The 14F, 24F, and 34F are supported by this driver.
37
 *
38
 *    Places flagged with a triple question-mark are things which are either
39
 *    unfinished, questionable, or wrong.
40
 */
41
 
42
/* Changes from version 1.11 alpha to 1.12
43
 *
44
 * Increased the size of the scatter-gather list to 33 entries for
45
 * the 24F adapter (it was 16).  I don't have the specs for the 14F
46
 * or the 34F, so they may support larger s-g lists as well.
47
 *
48
 * Caleb Epstein <cae@jpmorgan.com>
49
 */
50
 
51
/* Changes from version 1.9 to 1.11
52
 *
53
 * Patches to bring this driver up to speed with the default kernel
54
 * driver which supports only the 14F and 34F adapters.  This version
55
 * should compile cleanly into 0.99.13, 0.99.12 and probably 0.99.11.
56
 *
57
 * Fixes from Eric Youngdale to fix a few possible race conditions and
58
 * several problems with bit testing operations (insufficient
59
 * parentheses).
60
 *
61
 * Removed the ultrastor_abort() and ultrastor_reset() functions
62
 * (enclosed them in #if 0 / #endif).  These functions, at least on
63
 * the 24F, cause the SCSI bus to do odd things and generally lead to
64
 * kernel panics and machine hangs.  This is like the Adaptec code.
65
 *
66
 * Use check/snarf_region for 14f, 34f to avoid I/O space address conflicts.
67
 */
68
 
69
/* Changes from version 1.8 to version 1.9
70
 *
71
 *  0.99.11 patches (cae@jpmorgan.com) */
72
 
73
/* Changes from version 1.7 to version 1.8
74
 *
75
 * Better error reporting.
76
 */
77
 
78
/* Changes from version 1.6 to version 1.7
79
 *
80
 * Removed CSIR command code.
81
 *
82
 * Better race condition avoidance (xchgb function added).
83
 *
84
 * Set ICM and OGM status to zero at probe (24F)
85
 *
86
 * reset sends soft reset to UltraStor adapter
87
 *
88
 * reset adapter if adapter interrupts with an invalid MSCP address
89
 *
90
 * handle aborted command interrupt (24F)
91
 *
92
 */
93
 
94
/* Changes from version 1.5 to version 1.6:
95
 *
96
 * Read MSCP address from ICM _before_ clearing the interrupt flag.
97
 * This fixes a race condition.
98
 */
99
 
100
/* Changes from version 1.4 to version 1.5:
101
 *
102
 * Abort now calls done when multiple commands are enabled.
103
 *
104
 * Clear busy when aborted command finishes, not when abort is called.
105
 *
106
 * More debugging messages for aborts.
107
 */
108
 
109
/* Changes from version 1.3 to version 1.4:
110
 *
111
 * Enable automatic request of sense data on error (requires newer version
112
 * of scsi.c to be useful).
113
 *
114
 * Fix PORT_OVERRIDE for 14F.
115
 *
116
 * Fix abort and reset to work properly (config.aborted wasn't cleared
117
 * after it was tested, so after a command abort no further commands would
118
 * work).
119
 *
120
 * Boot time test to enable SCSI bus reset (defaults to not allowing reset).
121
 *
122
 * Fix test for OGM busy -- the busy bit is in different places on the 24F.
123
 *
124
 * Release ICM slot by clearing first byte on 24F.
125
 */
126
 
127
#ifdef MODULE
128
#include <linux/module.h>
129
#endif
130
 
131
#include <linux/stddef.h>
132
#include <linux/string.h>
133
#include <linux/sched.h>
134
#include <linux/kernel.h>
135
#include <linux/ioport.h>
136
#include <linux/proc_fs.h>
137
#include <asm/io.h>
138
#include <asm/bitops.h>
139
#include <asm/system.h>
140
#include <asm/dma.h>
141
 
142
#define ULTRASTOR_PRIVATE       /* Get the private stuff from ultrastor.h */
143
#include <linux/blk.h>
144
#include "scsi.h"
145
#include "hosts.h"
146
#include "ultrastor.h"
147
#include "sd.h"
148
#include<linux/stat.h>
149
 
150
struct proc_dir_entry proc_scsi_ultrastor = {
151
    PROC_SCSI_ULTRASTOR, 9, "ultrastor",
152
    S_IFDIR | S_IRUGO | S_IXUGO, 2
153
};
154
 
155
#define FALSE 0
156
#define TRUE 1
157
 
158
#ifndef ULTRASTOR_DEBUG
159
#define ULTRASTOR_DEBUG (UD_ABORT|UD_CSIR|UD_RESET)
160
#endif
161
 
162
#define VERSION "1.12"
163
 
164
#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0])
165
 
166
#define PACKED          __attribute__((packed))
167
#define ALIGNED(x)      __attribute__((aligned(x)))
168
 
169
 
170
/* The 14F uses an array of 4-byte ints for its scatter/gather list.
171
   The data can be unaligned, but need not be.  It's easier to give
172
   the list normal alignment since it doesn't need to fit into a
173
   packed structure.  */
174
 
175
typedef struct {
176
  unsigned int address;
177
  unsigned int num_bytes;
178
} ultrastor_sg_list;
179
 
180
 
181
/* MailBox SCSI Command Packet.  Basic command structure for communicating
182
   with controller. */
183
struct mscp {
184
  unsigned char opcode: 3;              /* type of command */
185
  unsigned char xdir: 2;                /* data transfer direction */
186
  unsigned char dcn: 1;         /* disable disconnect */
187
  unsigned char ca: 1;          /* use cache (if available) */
188
  unsigned char sg: 1;          /* scatter/gather operation */
189
  unsigned char target_id: 3;           /* target SCSI id */
190
  unsigned char ch_no: 2;               /* SCSI channel (always 0 for 14f) */
191
  unsigned char lun: 3;         /* logical unit number */
192
  unsigned int transfer_data PACKED;    /* transfer data pointer */
193
  unsigned int transfer_data_length PACKED;     /* length in bytes */
194
  unsigned int command_link PACKED;     /* for linking command chains */
195
  unsigned char scsi_command_link_id;   /* identifies command in chain */
196
  unsigned char number_of_sg_list;      /* (if sg is set) 8 bytes per list */
197
  unsigned char length_of_sense_byte;
198
  unsigned char length_of_scsi_cdbs;    /* 6, 10, or 12 */
199
  unsigned char scsi_cdbs[12];  /* SCSI commands */
200
  unsigned char adapter_status; /* non-zero indicates HA error */
201
  unsigned char target_status;  /* non-zero indicates target error */
202
  unsigned int sense_data PACKED;
203
  /* The following fields are for software only.  They are included in
204
     the MSCP structure because they are associated with SCSI requests.  */
205
  void (*done)(Scsi_Cmnd *);
206
  Scsi_Cmnd *SCint;
207
  ultrastor_sg_list sglist[ULTRASTOR_24F_MAX_SG]; /* use larger size for 24F */
208
};
209
 
210
 
211
/* Port addresses (relative to the base address) */
212
#define U14F_PRODUCT_ID(port) ((port) + 0x4)
213
#define CONFIG(port) ((port) + 0x6)
214
 
215
/* Port addresses relative to the doorbell base address.  */
216
#define LCL_DOORBELL_MASK(port) ((port) + 0x0)
217
#define LCL_DOORBELL_INTR(port) ((port) + 0x1)
218
#define SYS_DOORBELL_MASK(port) ((port) + 0x2)
219
#define SYS_DOORBELL_INTR(port) ((port) + 0x3)
220
 
221
 
222
/* Used to store configuration info read from config i/o registers.  Most of
223
   this is not used yet, but might as well save it.
224
 
225
   This structure also holds port addresses that are not at the same offset
226
   on the 14F and 24F.
227
 
228
   This structure holds all data that must be duplicated to support multiple
229
   adapters.  */
230
 
231
static struct ultrastor_config
232
{
233
  unsigned short port_address;          /* base address of card */
234
  unsigned short doorbell_address;      /* base address of doorbell CSRs */
235
  unsigned short ogm_address;           /* base address of OGM */
236
  unsigned short icm_address;           /* base address of ICM */
237
  const void *bios_segment;
238
  unsigned char interrupt: 4;
239
  unsigned char dma_channel: 3;
240
  unsigned char bios_drive_number: 1;
241
  unsigned char heads;
242
  unsigned char sectors;
243
  unsigned char ha_scsi_id: 3;
244
  unsigned char subversion: 4;
245
  unsigned char revision;
246
  /* The slot number is used to distinguish the 24F (slot != 0) from
247
     the 14F and 34F (slot == 0). */
248
  unsigned char slot;
249
 
250
#ifdef PRINT_U24F_VERSION
251
  volatile int csir_done;
252
#endif
253
 
254
  /* A pool of MSCP structures for this adapter, and a bitmask of
255
     busy structures.  (If ULTRASTOR_14F_MAX_CMDS == 1, a 1 byte
256
     busy flag is used instead.)  */
257
 
258
#if ULTRASTOR_MAX_CMDS == 1
259
  unsigned char mscp_busy;
260
#else
261
  unsigned short mscp_free;
262
#endif
263
  volatile unsigned char aborted[ULTRASTOR_MAX_CMDS];
264
  struct mscp mscp[ULTRASTOR_MAX_CMDS];
265
} config = {0};
266
 
267
/* Set this to 1 to reset the SCSI bus on error.  */
268
int ultrastor_bus_reset = 0;
269
 
270
 
271
/* Allowed BIOS base addresses (NULL indicates reserved) */
272
static const void *const bios_segment_table[8] = {
273
  NULL,      (void *)0xC4000, (void *)0xC8000, (void *)0xCC000,
274
  (void *)0xD0000, (void *)0xD4000, (void *)0xD8000, (void *)0xDC000,
275
};
276
 
277
/* Allowed IRQs for 14f */
278
static const unsigned char interrupt_table_14f[4] = { 15, 14, 11, 10 };
279
 
280
/* Allowed DMA channels for 14f (0 indicates reserved) */
281
static const unsigned char dma_channel_table_14f[4] = { 5, 6, 7, 0 };
282
 
283
/* Head/sector mappings allowed by 14f */
284
static const struct {
285
  unsigned char heads;
286
  unsigned char sectors;
287
} mapping_table[4] = { { 16, 63 }, { 64, 32 }, { 64, 63 }, { 64, 32 } };
288
 
289
#ifndef PORT_OVERRIDE
290
/* ??? A probe of address 0x310 screws up NE2000 cards */
291
static const unsigned short ultrastor_ports_14f[] = {
292
  0x330, 0x340, /*0x310,*/ 0x230, 0x240, 0x210, 0x130, 0x140,
293
};
294
#endif
295
 
296
static void ultrastor_interrupt(int, void *, struct pt_regs *);
297
static inline void build_sg_list(struct mscp *, Scsi_Cmnd *SCpnt);
298
 
299
 
300
static inline int find_and_clear_bit_16(unsigned short *field)
301
{
302
  int rv;
303
  unsigned long flags;
304
 
305
  save_flags(flags);
306
  cli();
307
  if (*field == 0) panic("No free mscp");
308
  asm("xorl %0,%0\n0:\tbsfw %1,%w0\n\tbtr %0,%1\n\tjnc 0b"
309
      : "=&r" (rv), "=m" (*field) : "1" (*field));
310
  restore_flags(flags);
311
  return rv;
312
}
313
 
314
/* This has been re-implemented with the help of Richard Earnshaw,
315
   <rwe@pegasus.esprit.ec.org> and works with gcc-2.5.8 and gcc-2.6.0.
316
   The instability noted by jfc below appears to be a bug in
317
   gcc-2.5.x when compiling w/o optimization.  --Caleb
318
 
319
   This asm is fragile: it doesn't work without the casts and it may
320
   not work without optimization.  Maybe I should add a swap builtin
321
   to gcc.  --jfc  */
322
static inline unsigned char xchgb(unsigned char reg,
323
                                  volatile unsigned char *mem)
324
{
325
  __asm__ ("xchgb %0,%1" : "=q" (reg), "=m" (*mem) : "0" (reg));
326
  return reg;
327
}
328
 
329
#if ULTRASTOR_DEBUG & (UD_COMMAND | UD_ABORT)
330
 
331
static void log_ultrastor_abort(register struct ultrastor_config *config,
332
                                int command)
333
{
334
  static char fmt[80] = "abort %d (%x); MSCP free pool: %x;";
335
  register int i;
336
  int flags;
337
  save_flags(flags);
338
  cli();
339
 
340
  for (i = 0; i < ULTRASTOR_MAX_CMDS; i++)
341
    {
342
      fmt[20 + i*2] = ' ';
343
      if (! (config->mscp_free & (1 << i)))
344
        fmt[21 + i*2] = '0' + config->mscp[i].target_id;
345
      else
346
        fmt[21 + i*2] = '-';
347
    }
348
  fmt[20 + ULTRASTOR_MAX_CMDS * 2] = '\n';
349
  fmt[21 + ULTRASTOR_MAX_CMDS * 2] = 0;
350
  printk(fmt, command, &config->mscp[command], config->mscp_free);
351
  restore_flags(flags);
352
}
353
#endif
354
 
355
static int ultrastor_14f_detect(Scsi_Host_Template * tpnt)
356
{
357
    size_t i;
358
    unsigned char in_byte, version_byte = 0;
359
    struct config_1 {
360
      unsigned char bios_segment: 3;
361
      unsigned char removable_disks_as_fixed: 1;
362
      unsigned char interrupt: 2;
363
    unsigned char dma_channel: 2;
364
    } config_1;
365
    struct config_2 {
366
      unsigned char ha_scsi_id: 3;
367
      unsigned char mapping_mode: 2;
368
      unsigned char bios_drive_number: 1;
369
      unsigned char tfr_port: 2;
370
    } config_2;
371
 
372
#if (ULTRASTOR_DEBUG & UD_DETECT)
373
    printk("US14F: detect: called\n");
374
#endif
375
 
376
    /* If a 24F has already been configured, don't look for a 14F.  */
377
    if (config.bios_segment)
378
        return FALSE;
379
 
380
#ifdef PORT_OVERRIDE
381
    if(check_region(PORT_OVERRIDE, 0xc)) {
382
      printk("Ultrastor I/O space already in use\n");
383
      return FALSE;
384
    };
385
    config.port_address = PORT_OVERRIDE;
386
#else
387
    for (i = 0; i < ARRAY_SIZE(ultrastor_ports_14f); i++) {
388
      if(check_region(ultrastor_ports_14f[i], 0x0c)) continue;
389
      config.port_address = ultrastor_ports_14f[i];
390
#endif
391
 
392
#if (ULTRASTOR_DEBUG & UD_DETECT)
393
        printk("US14F: detect: testing port address %03X\n", config.port_address);
394
#endif
395
 
396
        in_byte = inb(U14F_PRODUCT_ID(config.port_address));
397
        if (in_byte != US14F_PRODUCT_ID_0) {
398
#if (ULTRASTOR_DEBUG & UD_DETECT)
399
# ifdef PORT_OVERRIDE
400
            printk("US14F: detect: wrong product ID 0 - %02X\n", in_byte);
401
# else
402
            printk("US14F: detect: no adapter at port %03X\n", config.port_address);
403
# endif
404
#endif
405
#ifdef PORT_OVERRIDE
406
            return FALSE;
407
#else
408
            continue;
409
#endif
410
        }
411
        in_byte = inb(U14F_PRODUCT_ID(config.port_address) + 1);
412
        /* Only upper nibble is significant for Product ID 1 */
413
        if ((in_byte & 0xF0) != US14F_PRODUCT_ID_1) {
414
#if (ULTRASTOR_DEBUG & UD_DETECT)
415
# ifdef PORT_OVERRIDE
416
            printk("US14F: detect: wrong product ID 1 - %02X\n", in_byte);
417
# else
418
            printk("US14F: detect: no adapter at port %03X\n", config.port_address);
419
# endif
420
#endif
421
#ifdef PORT_OVERRIDE
422
            return FALSE;
423
#else
424
            continue;
425
#endif
426
        }
427
        version_byte = in_byte;
428
#ifndef PORT_OVERRIDE
429
        break;
430
    }
431
    if (i == ARRAY_SIZE(ultrastor_ports_14f)) {
432
# if (ULTRASTOR_DEBUG & UD_DETECT)
433
        printk("US14F: detect: no port address found!\n");
434
# endif
435
        return FALSE;
436
    }
437
#endif
438
 
439
#if (ULTRASTOR_DEBUG & UD_DETECT)
440
    printk("US14F: detect: adapter found at port address %03X\n",
441
           config.port_address);
442
#endif
443
 
444
    /* Set local doorbell mask to disallow bus reset unless
445
       ultrastor_bus_reset is true.  */
446
    outb(ultrastor_bus_reset ? 0xc2 : 0x82, LCL_DOORBELL_MASK(config.port_address));
447
 
448
    /* All above tests passed, must be the right thing.  Get some useful
449
       info. */
450
 
451
    request_region(config.port_address, 0x0c,"ultrastor");
452
    /* Register the I/O space that we use */
453
 
454
    *(char *)&config_1 = inb(CONFIG(config.port_address + 0));
455
    *(char *)&config_2 = inb(CONFIG(config.port_address + 1));
456
    config.bios_segment = bios_segment_table[config_1.bios_segment];
457
    config.doorbell_address = config.port_address;
458
    config.ogm_address = config.port_address + 0x8;
459
    config.icm_address = config.port_address + 0xC;
460
    config.interrupt = interrupt_table_14f[config_1.interrupt];
461
    config.ha_scsi_id = config_2.ha_scsi_id;
462
    config.heads = mapping_table[config_2.mapping_mode].heads;
463
    config.sectors = mapping_table[config_2.mapping_mode].sectors;
464
    config.bios_drive_number = config_2.bios_drive_number;
465
    config.subversion = (version_byte & 0x0F);
466
    if (config.subversion == U34F)
467
        config.dma_channel = 0;
468
    else
469
        config.dma_channel = dma_channel_table_14f[config_1.dma_channel];
470
 
471
    if (!config.bios_segment) {
472
#if (ULTRASTOR_DEBUG & UD_DETECT)
473
        printk("US14F: detect: not detected.\n");
474
#endif
475
        return FALSE;
476
    }
477
 
478
    /* Final consistency check, verify previous info. */
479
    if (config.subversion != U34F)
480
        if (!config.dma_channel || !(config_2.tfr_port & 0x2)) {
481
#if (ULTRASTOR_DEBUG & UD_DETECT)
482
            printk("US14F: detect: consistency check failed\n");
483
#endif
484
            return FALSE;
485
        }
486
 
487
    /* If we were TRULY paranoid, we could issue a host adapter inquiry
488
       command here and verify the data returned.  But frankly, I'm
489
       exhausted! */
490
 
491
    /* Finally!  Now I'm satisfied... */
492
#if (ULTRASTOR_DEBUG & UD_DETECT)
493
    printk("US14F: detect: detect succeeded\n"
494
           "  Port address: %03X\n"
495
           "  BIOS segment: %05X\n"
496
           "  Interrupt: %u\n"
497
           "  DMA channel: %u\n"
498
           "  H/A SCSI ID: %u\n"
499
           "  Subversion: %u\n",
500
           config.port_address, config.bios_segment, config.interrupt,
501
           config.dma_channel, config.ha_scsi_id, config.subversion);
502
#endif
503
    tpnt->this_id = config.ha_scsi_id;
504
    tpnt->unchecked_isa_dma = (config.subversion != U34F);
505
 
506
#if ULTRASTOR_MAX_CMDS > 1
507
    config.mscp_free = ~0;
508
#endif
509
 
510
    if (request_irq(config.interrupt, ultrastor_interrupt, 0, "Ultrastor", NULL)) {
511
        printk("Unable to allocate IRQ%u for UltraStor controller.\n",
512
               config.interrupt);
513
        return FALSE;
514
    }
515
    if (config.dma_channel && request_dma(config.dma_channel,"Ultrastor")) {
516
        printk("Unable to allocate DMA channel %u for UltraStor controller.\n",
517
               config.dma_channel);
518
        free_irq(config.interrupt, NULL);
519
        return FALSE;
520
    }
521
    tpnt->sg_tablesize = ULTRASTOR_14F_MAX_SG;
522
    printk("UltraStor driver version" VERSION ".  Using %d SG lists.\n",
523
           ULTRASTOR_14F_MAX_SG);
524
 
525
    return TRUE;
526
}
527
 
528
static int ultrastor_24f_detect(Scsi_Host_Template * tpnt)
529
{
530
  register int i;
531
  struct Scsi_Host * shpnt = NULL;
532
 
533
#if (ULTRASTOR_DEBUG & UD_DETECT)
534
  printk("US24F: detect");
535
#endif
536
 
537
  /* probe each EISA slot at slot address C80 */
538
  for (i = 1; i < 15; i++)
539
    {
540
      unsigned char config_1, config_2;
541
      unsigned short addr = (i << 12) | ULTRASTOR_24F_PORT;
542
 
543
      if (inb(addr) != US24F_PRODUCT_ID_0 &&
544
          inb(addr+1) != US24F_PRODUCT_ID_1 &&
545
          inb(addr+2) != US24F_PRODUCT_ID_2)
546
        continue;
547
 
548
      config.revision = inb(addr+3);
549
      config.slot = i;
550
      if (! (inb(addr+4) & 1))
551
        {
552
#if (ULTRASTOR_DEBUG & UD_DETECT)
553
          printk("U24F: found disabled card in slot %u\n", i);
554
#endif
555
          continue;
556
        }
557
#if (ULTRASTOR_DEBUG & UD_DETECT)
558
      printk("U24F: found card in slot %u\n", i);
559
#endif
560
      config_1 = inb(addr + 5);
561
      config.bios_segment = bios_segment_table[config_1 & 7];
562
      switch(config_1 >> 4)
563
        {
564
        case 1:
565
          config.interrupt = 15;
566
          break;
567
        case 2:
568
          config.interrupt = 14;
569
          break;
570
        case 4:
571
          config.interrupt = 11;
572
          break;
573
        case 8:
574
          config.interrupt = 10;
575
          break;
576
        default:
577
          printk("U24F: invalid IRQ\n");
578
          return FALSE;
579
        }
580
      if (request_irq(config.interrupt, ultrastor_interrupt, 0, "Ultrastor", NULL))
581
        {
582
          printk("Unable to allocate IRQ%u for UltraStor controller.\n",
583
                 config.interrupt);
584
          return FALSE;
585
        }
586
      /* BIOS addr set */
587
      /* base port set */
588
      config.port_address = addr;
589
      config.doorbell_address = addr + 12;
590
      config.ogm_address = addr + 0x17;
591
      config.icm_address = addr + 0x1C;
592
      config_2 = inb(addr + 7);
593
      config.ha_scsi_id = config_2 & 7;
594
      config.heads = mapping_table[(config_2 >> 3) & 3].heads;
595
      config.sectors = mapping_table[(config_2 >> 3) & 3].sectors;
596
#if (ULTRASTOR_DEBUG & UD_DETECT)
597
      printk("US24F: detect: detect succeeded\n"
598
             "  Port address: %03X\n"
599
             "  BIOS segment: %05X\n"
600
             "  Interrupt: %u\n"
601
             "  H/A SCSI ID: %u\n",
602
             config.port_address, config.bios_segment,
603
             config.interrupt, config.ha_scsi_id);
604
#endif
605
      tpnt->this_id = config.ha_scsi_id;
606
      tpnt->unchecked_isa_dma = 0;
607
      tpnt->sg_tablesize = ULTRASTOR_24F_MAX_SG;
608
 
609
      shpnt = scsi_register(tpnt, 0);
610
      shpnt->irq = config.interrupt;
611
      shpnt->dma_channel = config.dma_channel;
612
      shpnt->io_port = config.port_address;
613
 
614
#if ULTRASTOR_MAX_CMDS > 1
615
      config.mscp_free = ~0;
616
#endif
617
      /* Mark ICM and OGM free */
618
      outb(0, addr + 0x16);
619
      outb(0, addr + 0x1B);
620
 
621
      /* Set local doorbell mask to disallow bus reset unless
622
         ultrastor_bus_reset is true.  */
623
      outb(ultrastor_bus_reset ? 0xc2 : 0x82, LCL_DOORBELL_MASK(addr+12));
624
      outb(0x02, SYS_DOORBELL_MASK(addr+12));
625
      printk("UltraStor driver version " VERSION ".  Using %d SG lists.\n",
626
             tpnt->sg_tablesize);
627
      return TRUE;
628
    }
629
  return FALSE;
630
}
631
 
632
int ultrastor_detect(Scsi_Host_Template * tpnt)
633
{
634
    tpnt->proc_dir = &proc_scsi_ultrastor;
635
  return ultrastor_14f_detect(tpnt) || ultrastor_24f_detect(tpnt);
636
}
637
 
638
const char *ultrastor_info(struct Scsi_Host * shpnt)
639
{
640
    static char buf[64];
641
 
642
    if (config.slot)
643
      sprintf(buf, "UltraStor 24F SCSI @ Slot %u IRQ%u",
644
              config.slot, config.interrupt);
645
    else if (config.subversion)
646
      sprintf(buf, "UltraStor 34F SCSI @ Port %03X BIOS %05X IRQ%u",
647
              config.port_address, (int)config.bios_segment,
648
              config.interrupt);
649
    else
650
      sprintf(buf, "UltraStor 14F SCSI @ Port %03X BIOS %05X IRQ%u DMA%u",
651
              config.port_address, (int)config.bios_segment,
652
              config.interrupt, config.dma_channel);
653
    return buf;
654
}
655
 
656
static inline void build_sg_list(register struct mscp *mscp, Scsi_Cmnd *SCpnt)
657
{
658
        struct scatterlist *sl;
659
        long transfer_length = 0;
660
        int i, max;
661
 
662
        sl = (struct scatterlist *) SCpnt->request_buffer;
663
        max = SCpnt->use_sg;
664
        for (i = 0; i < max; i++) {
665
                mscp->sglist[i].address = (unsigned int)sl[i].address;
666
                mscp->sglist[i].num_bytes = sl[i].length;
667
                transfer_length += sl[i].length;
668
        }
669
        mscp->number_of_sg_list = max;
670
        mscp->transfer_data = (unsigned int)mscp->sglist;
671
        /* ??? May not be necessary.  Docs are unclear as to whether transfer
672
           length field is ignored or whether it should be set to the total
673
           number of bytes of the transfer.  */
674
        mscp->transfer_data_length = transfer_length;
675
}
676
 
677
int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
678
{
679
    register struct mscp *my_mscp;
680
#if ULTRASTOR_MAX_CMDS > 1
681
    int mscp_index;
682
#endif
683
    unsigned int status;
684
    int flags;
685
 
686
    /* Next test is for debugging; "can't happen" */
687
    if ((config.mscp_free & ((1U << ULTRASTOR_MAX_CMDS) - 1)) == 0)
688
        panic("ultrastor_queuecommand: no free MSCP\n");
689
    mscp_index = find_and_clear_bit_16(&config.mscp_free);
690
 
691
    /* Has the command been aborted?  */
692
    if (xchgb(0xff, &config.aborted[mscp_index]) != 0)
693
      {
694
        status = DID_ABORT << 16;
695
        goto aborted;
696
      }
697
 
698
    my_mscp = &config.mscp[mscp_index];
699
 
700
#if 1
701
    /* This way is faster.  */
702
    *(unsigned char *)my_mscp = OP_SCSI | (DTD_SCSI << 3);
703
#else
704
    my_mscp->opcode = OP_SCSI;
705
    my_mscp->xdir = DTD_SCSI;
706
    my_mscp->dcn = FALSE;
707
#endif
708
    /* Tape drives don't work properly if the cache is used.  The SCSI
709
       READ command for a tape doesn't have a block offset, and the adapter
710
       incorrectly assumes that all reads from the tape read the same
711
       blocks.  Results will depend on read buffer size and other disk
712
       activity.
713
 
714
       ???  Which other device types should never use the cache?   */
715
    my_mscp->ca = SCpnt->device->type != TYPE_TAPE;
716
    my_mscp->target_id = SCpnt->target;
717
    my_mscp->ch_no = 0;
718
    my_mscp->lun = SCpnt->lun;
719
    if (SCpnt->use_sg) {
720
        /* Set scatter/gather flag in SCSI command packet */
721
        my_mscp->sg = TRUE;
722
        build_sg_list(my_mscp, SCpnt);
723
    } else {
724
        /* Unset scatter/gather flag in SCSI command packet */
725
        my_mscp->sg = FALSE;
726
        my_mscp->transfer_data = (unsigned int)SCpnt->request_buffer;
727
        my_mscp->transfer_data_length = SCpnt->request_bufflen;
728
    }
729
    my_mscp->command_link = 0;           /*???*/
730
    my_mscp->scsi_command_link_id = 0;   /*???*/
731
    my_mscp->length_of_sense_byte = sizeof SCpnt->sense_buffer;
732
    my_mscp->length_of_scsi_cdbs = SCpnt->cmd_len;
733
    memcpy(my_mscp->scsi_cdbs, SCpnt->cmnd, my_mscp->length_of_scsi_cdbs);
734
    my_mscp->adapter_status = 0;
735
    my_mscp->target_status = 0;
736
    my_mscp->sense_data = (unsigned int)&SCpnt->sense_buffer;
737
    my_mscp->done = done;
738
    my_mscp->SCint = SCpnt;
739
    SCpnt->host_scribble = (unsigned char *)my_mscp;
740
 
741
    /* Find free OGM slot.  On 24F, look for OGM status byte == 0.
742
       On 14F and 34F, wait for local interrupt pending flag to clear.  */
743
 
744
  retry:
745
    if (config.slot)
746
        while (inb(config.ogm_address - 1) != 0 &&
747
               config.aborted[mscp_index] == 0xff) barrier();
748
 
749
    /* else??? */
750
 
751
    while ((inb(LCL_DOORBELL_INTR(config.doorbell_address)) &
752
            (config.slot ? 2 : 1))
753
           && config.aborted[mscp_index] == 0xff) barrier();
754
 
755
    /* To avoid race conditions, make the code to write to the adapter
756
       atomic.  This simplifies the abort code.  */
757
 
758
    save_flags(flags);
759
    cli();
760
 
761
    if (inb(LCL_DOORBELL_INTR(config.doorbell_address)) &
762
        (config.slot ? 2 : 1))
763
      {
764
      restore_flags(flags);
765
      goto retry;
766
      }
767
 
768
    status = xchgb(0, &config.aborted[mscp_index]);
769
    if (status != 0xff) {
770
        restore_flags(flags);
771
 
772
#if ULTRASTOR_DEBUG & (UD_COMMAND | UD_ABORT)
773
        printk("USx4F: queuecommand: aborted\n");
774
#if ULTRASTOR_MAX_CMDS > 1
775
        log_ultrastor_abort(&config, mscp_index);
776
#endif
777
#endif
778
        status <<= 16;
779
 
780
      aborted:
781
        set_bit(mscp_index, &config.mscp_free);
782
        /* If the driver queues commands, call the done proc here.  Otherwise
783
           return an error.  */
784
#if ULTRASTOR_MAX_CMDS > 1
785
        SCpnt->result = status;
786
        done(SCpnt);
787
        return 0;
788
#else
789
        return status;
790
#endif
791
    }
792
 
793
    /* Store pointer in OGM address bytes */
794
    outl((unsigned int)my_mscp, config.ogm_address);
795
 
796
    /* Issue OGM interrupt */
797
    if (config.slot) {
798
        /* Write OGM command register on 24F */
799
        outb(1, config.ogm_address - 1);
800
        outb(0x2, LCL_DOORBELL_INTR(config.doorbell_address));
801
    } else {
802
        outb(0x1, LCL_DOORBELL_INTR(config.doorbell_address));
803
    }
804
 
805
    restore_flags(flags);
806
 
807
#if (ULTRASTOR_DEBUG & UD_COMMAND)
808
    printk("USx4F: queuecommand: returning\n");
809
#endif
810
 
811
    return 0;
812
}
813
 
814
/* This code must deal with 2 cases:
815
 
816
   1. The command has not been written to the OGM.  In this case, set
817
   the abort flag and return.
818
 
819
   2. The command has been written to the OGM and is stuck somewhere in
820
   the adapter.
821
 
822
   2a.  On a 24F, ask the adapter to abort the command.  It will interrupt
823
   when it does.
824
 
825
   2b.  Call the command's done procedure.
826
 
827
 */
828
 
829
int ultrastor_abort(Scsi_Cmnd *SCpnt)
830
{
831
#if ULTRASTOR_DEBUG & UD_ABORT
832
    char out[108];
833
    unsigned char icm_status = 0, ogm_status = 0;
834
    unsigned int icm_addr = 0, ogm_addr = 0;
835
#endif
836
    unsigned int mscp_index;
837
    unsigned char old_aborted;
838
    void (*done)(Scsi_Cmnd *);
839
 
840
    if(config.slot)
841
      return SCSI_ABORT_SNOOZE;  /* Do not attempt an abort for the 24f */
842
 
843
    /* Simple consistency checking */
844
    if(!SCpnt->host_scribble)
845
      return SCSI_ABORT_NOT_RUNNING;
846
 
847
    mscp_index = ((struct mscp *)SCpnt->host_scribble) - config.mscp;
848
    if (mscp_index >= ULTRASTOR_MAX_CMDS)
849
        panic("Ux4F aborting invalid MSCP");
850
 
851
#if ULTRASTOR_DEBUG & UD_ABORT
852
    if (config.slot)
853
      {
854
        int port0 = (config.slot << 12) | 0xc80;
855
        int i;
856
        int flags;
857
        save_flags(flags);
858
        cli();
859
        strcpy(out, "OGM %d:%x ICM %d:%x ports:  ");
860
        for (i = 0; i < 16; i++)
861
          {
862
            unsigned char p = inb(port0 + i);
863
            out[28 + i * 3] = "0123456789abcdef"[p >> 4];
864
            out[29 + i * 3] = "0123456789abcdef"[p & 15];
865
            out[30 + i * 3] = ' ';
866
          }
867
        out[28 + i * 3] = '\n';
868
        out[29 + i * 3] = 0;
869
        ogm_status = inb(port0 + 22);
870
        ogm_addr = inl(port0 + 23);
871
        icm_status = inb(port0 + 27);
872
        icm_addr = inl(port0 + 28);
873
        restore_flags(flags);
874
      }
875
 
876
    /* First check to see if an interrupt is pending.  I suspect the SiS
877
       chipset loses interrupts.  (I also suspect is mangles data, but
878
       one bug at a time... */
879
    if (config.slot ? inb(config.icm_address - 1) == 2 :
880
        (inb(SYS_DOORBELL_INTR(config.doorbell_address)) & 1))
881
      {
882
        int flags;
883
        save_flags(flags);
884
        printk("Ux4F: abort while completed command pending\n");
885
        restore_flags(flags);
886
        cli();
887
        ultrastor_interrupt(0, NULL, NULL);
888
        restore_flags(flags);
889
        return SCSI_ABORT_SUCCESS;  /* FIXME - is this correct? -ERY */
890
      }
891
#endif
892
 
893
    old_aborted = xchgb(DID_ABORT, &config.aborted[mscp_index]);
894
 
895
    /* aborted == 0xff is the signal that queuecommand has not yet sent
896
       the command.  It will notice the new abort flag and fail.  */
897
    if (old_aborted == 0xff)
898
        return SCSI_ABORT_SUCCESS;
899
 
900
    /* On 24F, send an abort MSCP request.  The adapter will interrupt
901
       and the interrupt handler will call done.  */
902
    if (config.slot && inb(config.ogm_address - 1) == 0)
903
      {
904
        int flags;
905
 
906
        save_flags(flags);
907
        cli();
908
        outl((int)&config.mscp[mscp_index], config.ogm_address);
909
        inb(0xc80);     /* delay */
910
        outb(0x80, config.ogm_address - 1);
911
        outb(0x2, LCL_DOORBELL_INTR(config.doorbell_address));
912
#if ULTRASTOR_DEBUG & UD_ABORT
913
        log_ultrastor_abort(&config, mscp_index);
914
        printk(out, ogm_status, ogm_addr, icm_status, icm_addr);
915
#endif
916
        restore_flags(flags);
917
        return SCSI_ABORT_PENDING;
918
      }
919
 
920
#if ULTRASTOR_DEBUG & UD_ABORT
921
    log_ultrastor_abort(&config, mscp_index);
922
#endif
923
 
924
    /* Can't request a graceful abort.  Either this is not a 24F or
925
       the OGM is busy.  Don't free the command -- the adapter might
926
       still be using it.  Setting SCint = 0 causes the interrupt
927
       handler to ignore the command.  */
928
 
929
    /* FIXME - devices that implement soft resets will still be running
930
       the command after a bus reset.  We would probably rather leave
931
       the command in the queue.  The upper level code will automatically
932
       leave the command in the active state instead of requeueing it. ERY */
933
 
934
#if ULTRASTOR_DEBUG & UD_ABORT
935
    if (config.mscp[mscp_index].SCint != SCpnt)
936
        printk("abort: command mismatch, %p != %p\n",
937
               config.mscp[mscp_index].SCint, SCpnt);
938
#endif
939
    if (config.mscp[mscp_index].SCint == 0)
940
        return SCSI_ABORT_NOT_RUNNING;
941
 
942
    if (config.mscp[mscp_index].SCint != SCpnt) panic("Bad abort");
943
    config.mscp[mscp_index].SCint = 0;
944
    done = config.mscp[mscp_index].done;
945
    config.mscp[mscp_index].done = 0;
946
    SCpnt->result = DID_ABORT << 16;
947
    /* I worry about reentrancy in scsi.c  */
948
    done(SCpnt);
949
 
950
    /* Need to set a timeout here in case command never completes.  */
951
    return SCSI_ABORT_SUCCESS;
952
}
953
 
954
int ultrastor_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
955
{
956
    int flags;
957
    register int i;
958
#if (ULTRASTOR_DEBUG & UD_RESET)
959
    printk("US14F: reset: called\n");
960
#endif
961
 
962
    if(config.slot)
963
      return SCSI_RESET_PUNT;  /* Do not attempt a reset for the 24f */
964
 
965
    save_flags(flags);
966
    cli();
967
 
968
    /* Reset the adapter and SCSI bus.  The SCSI bus reset can be
969
       inhibited by clearing ultrastor_bus_reset before probe.  */
970
    outb(0xc0, LCL_DOORBELL_INTR(config.doorbell_address));
971
    if (config.slot)
972
      {
973
        outb(0, config.ogm_address - 1);
974
        outb(0, config.icm_address - 1);
975
      }
976
 
977
#if ULTRASTOR_MAX_CMDS == 1
978
    if (config.mscp_busy && config.mscp->done && config.mscp->SCint)
979
      {
980
        config.mscp->SCint->result = DID_RESET << 16;
981
        config.mscp->done(config.mscp->SCint);
982
      }
983
    config.mscp->SCint = 0;
984
#else
985
    for (i = 0; i < ULTRASTOR_MAX_CMDS; i++)
986
      {
987
        if (! (config.mscp_free & (1 << i)) &&
988
            config.mscp[i].done && config.mscp[i].SCint)
989
          {
990
            config.mscp[i].SCint->result = DID_RESET << 16;
991
            config.mscp[i].done(config.mscp[i].SCint);
992
            config.mscp[i].done = 0;
993
          }
994
        config.mscp[i].SCint = 0;
995
      }
996
#endif
997
 
998
    /* FIXME - if the device implements soft resets, then the command
999
       will still be running.  ERY */
1000
 
1001
    memset((unsigned char *)config.aborted, 0, sizeof config.aborted);
1002
#if ULTRASTOR_MAX_CMDS == 1
1003
    config.mscp_busy = 0;
1004
#else
1005
    config.mscp_free = ~0;
1006
#endif
1007
 
1008
    restore_flags(flags);
1009
    return SCSI_RESET_SUCCESS;
1010
 
1011
}
1012
 
1013
int ultrastor_biosparam(Disk * disk, kdev_t dev, int * dkinfo)
1014
{
1015
    int size = disk->capacity;
1016
    unsigned int s = config.heads * config.sectors;
1017
 
1018
    dkinfo[0] = config.heads;
1019
    dkinfo[1] = config.sectors;
1020
    dkinfo[2] = size / s;       /* Ignore partial cylinders */
1021
#if 0
1022
    if (dkinfo[2] > 1024)
1023
        dkinfo[2] = 1024;
1024
#endif
1025
    return 0;
1026
}
1027
 
1028
static void ultrastor_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1029
{
1030
    unsigned int status;
1031
#if ULTRASTOR_MAX_CMDS > 1
1032
    unsigned int mscp_index;
1033
#endif
1034
    register struct mscp *mscp;
1035
    void (*done)(Scsi_Cmnd *);
1036
    Scsi_Cmnd *SCtmp;
1037
 
1038
#if ULTRASTOR_MAX_CMDS == 1
1039
    mscp = &config.mscp[0];
1040
#else
1041
    mscp = (struct mscp *)inl(config.icm_address);
1042
    mscp_index = mscp - config.mscp;
1043
    if (mscp_index >= ULTRASTOR_MAX_CMDS) {
1044
        printk("Ux4F interrupt: bad MSCP address %x\n", (unsigned int) mscp);
1045
        /* A command has been lost.  Reset and report an error
1046
           for all commands.  */
1047
        ultrastor_reset(NULL, 0);
1048
        return;
1049
    }
1050
#endif
1051
 
1052
    /* Clean ICM slot (set ICMINT bit to 0) */
1053
    if (config.slot) {
1054
        unsigned char icm_status = inb(config.icm_address - 1);
1055
#if ULTRASTOR_DEBUG & (UD_INTERRUPT|UD_ERROR|UD_ABORT)
1056
        if (icm_status != 1 && icm_status != 2)
1057
            printk("US24F: ICM status %x for MSCP %d (%x)\n", icm_status,
1058
                   mscp_index, (unsigned int) mscp);
1059
#endif
1060
        /* The manual says clear interrupt then write 0 to ICM status.
1061
           This seems backwards, but I'll do it anyway.  --jfc */
1062
        outb(2, SYS_DOORBELL_INTR(config.doorbell_address));
1063
        outb(0, config.icm_address - 1);
1064
        if (icm_status == 4) {
1065
            printk("UltraStor abort command failed\n");
1066
            return;
1067
        }
1068
        if (icm_status == 3) {
1069
            void (*done)(Scsi_Cmnd *) = mscp->done;
1070
            if (done) {
1071
                mscp->done = 0;
1072
                mscp->SCint->result = DID_ABORT << 16;
1073
                done(mscp->SCint);
1074
            }
1075
            return;
1076
        }
1077
    } else {
1078
        outb(1, SYS_DOORBELL_INTR(config.doorbell_address));
1079
    }
1080
 
1081
    SCtmp = mscp->SCint;
1082
    mscp->SCint = NULL;
1083
 
1084
    if (SCtmp == 0)
1085
      {
1086
#if ULTRASTOR_DEBUG & (UD_ABORT|UD_INTERRUPT)
1087
        printk("MSCP %d (%x): no command\n", mscp_index, (unsigned int) mscp);
1088
#endif  
1089
#if ULTRASTOR_MAX_CMDS == 1
1090
        config.mscp_busy = FALSE;
1091
#else
1092
        set_bit(mscp_index, &config.mscp_free);
1093
#endif
1094
        config.aborted[mscp_index] = 0;
1095
        return;
1096
      }
1097
 
1098
    /* Save done locally and zero before calling.  This is needed as
1099
       once we call done, we may get another command queued before this
1100
       interrupt service routine can return. */
1101
    done = mscp->done;
1102
    mscp->done = 0;
1103
 
1104
    /* Let the higher levels know that we're done */
1105
    switch (mscp->adapter_status)
1106
      {
1107
      case 0:
1108
        status = DID_OK << 16;
1109
        break;
1110
      case 0x01:        /* invalid command */
1111
      case 0x02:        /* invalid parameters */
1112
      case 0x03:        /* invalid data list */
1113
      default:
1114
        status = DID_ERROR << 16;
1115
        break;
1116
      case 0x84:        /* SCSI bus abort */
1117
        status = DID_ABORT << 16;
1118
        break;
1119
      case 0x91:
1120
        status = DID_TIME_OUT << 16;
1121
        break;
1122
      }
1123
 
1124
    SCtmp->result = status | mscp->target_status;
1125
 
1126
    SCtmp->host_scribble = 0;
1127
 
1128
    /* Free up mscp block for next command */
1129
#if ULTRASTOR_MAX_CMDS == 1
1130
    config.mscp_busy = FALSE;
1131
#else
1132
    set_bit(mscp_index, &config.mscp_free);
1133
#endif
1134
 
1135
#if ULTRASTOR_DEBUG & (UD_ABORT|UD_INTERRUPT)
1136
    if (config.aborted[mscp_index])
1137
        printk("Ux4 interrupt: MSCP %d (%x) aborted = %d\n",
1138
               mscp_index, (unsigned int) mscp, config.aborted[mscp_index]);
1139
#endif
1140
    config.aborted[mscp_index] = 0;
1141
 
1142
    if (done)
1143
        done(SCtmp);
1144
    else
1145
        printk("US14F: interrupt: unexpected interrupt\n");
1146
 
1147
    if (config.slot ? inb(config.icm_address - 1) :
1148
       (inb(SYS_DOORBELL_INTR(config.doorbell_address)) & 1))
1149
#if (ULTRASTOR_DEBUG & UD_MULTI_CMD)
1150
      printk("Ux4F: multiple commands completed\n");
1151
#else
1152
      ;
1153
#endif
1154
 
1155
#if (ULTRASTOR_DEBUG & UD_INTERRUPT)
1156
    printk("USx4F: interrupt: returning\n");
1157
#endif
1158
}
1159
 
1160
#ifdef MODULE
1161
/* Eventually this will go into an include file, but this will be later */
1162
Scsi_Host_Template driver_template = ULTRASTOR_14F;
1163
 
1164
#include "scsi_module.c"
1165
#endif

powered by: WebSVN 2.1.0

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