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