linux/drivers/scsi/g_NCR5380.c
<<
>>
Prefs
   1/*
   2 * Generic Generic NCR5380 driver
   3 *      
   4 * Copyright 1993, Drew Eckhardt
   5 *      Visionary Computing
   6 *      (Unix and Linux consulting and custom programming)
   7 *      drew@colorado.edu
   8 *      +1 (303) 440-4894
   9 *
  10 * NCR53C400 extensions (c) 1994,1995,1996, Kevin Lentin
  11 *    K.Lentin@cs.monash.edu.au
  12 *
  13 * NCR53C400A extensions (c) 1996, Ingmar Baumgart
  14 *    ingmar@gonzo.schwaben.de
  15 *
  16 * DTC3181E extensions (c) 1997, Ronald van Cuijlenborg
  17 * ronald.van.cuijlenborg@tip.nl or nutty@dds.nl
  18 *
  19 * Added ISAPNP support for DTC436 adapters,
  20 * Thomas Sailer, sailer@ife.ee.ethz.ch
  21 */
  22
  23/* 
  24 * TODO : flesh out DMA support, find some one actually using this (I have
  25 *      a memory mapped Trantor board that works fine)
  26 */
  27
  28/*
  29 * The card is detected and initialized in one of several ways : 
  30 * 1.  With command line overrides - NCR5380=port,irq may be 
  31 *     used on the LILO command line to override the defaults.
  32 *
  33 * 2.  With the GENERIC_NCR5380_OVERRIDE compile time define.  This is 
  34 *     specified as an array of address, irq, dma, board tuples.  Ie, for
  35 *     one board at 0x350, IRQ5, no dma, I could say  
  36 *     -DGENERIC_NCR5380_OVERRIDE={{0xcc000, 5, DMA_NONE, BOARD_NCR5380}}
  37 * 
  38 * -1 should be specified for no or DMA interrupt, -2 to autoprobe for an 
  39 *      IRQ line if overridden on the command line.
  40 *
  41 * 3.  When included as a module, with arguments passed on the command line:
  42 *         ncr_irq=xx   the interrupt
  43 *         ncr_addr=xx  the port or base address (for port or memory
  44 *                      mapped, resp.)
  45 *         ncr_dma=xx   the DMA
  46 *         ncr_5380=1   to set up for a NCR5380 board
  47 *         ncr_53c400=1 to set up for a NCR53C400 board
  48 *     e.g.
  49 *     modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_5380=1
  50 *       for a port mapped NCR5380 board or
  51 *     modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1
  52 *       for a memory mapped NCR53C400 board with interrupts disabled.
  53 * 
  54 * 255 should be specified for no or DMA interrupt, 254 to autoprobe for an 
  55 *      IRQ line if overridden on the command line.
  56 *     
  57 */
  58
  59/* settings for DTC3181E card with only Mustek scanner attached */
  60#define USLEEP_POLL     msecs_to_jiffies(10)
  61#define USLEEP_SLEEP    msecs_to_jiffies(200)
  62#define USLEEP_WAITLONG msecs_to_jiffies(5000)
  63
  64#define AUTOPROBE_IRQ
  65
  66#ifdef CONFIG_SCSI_GENERIC_NCR53C400
  67#define NCR53C400_PSEUDO_DMA 1
  68#define PSEUDO_DMA
  69#define NCR53C400
  70#endif
  71
  72#include <asm/io.h>
  73#include <linux/signal.h>
  74#include <linux/blkdev.h>
  75#include <scsi/scsi_host.h>
  76#include "g_NCR5380.h"
  77#include "NCR5380.h"
  78#include <linux/stat.h>
  79#include <linux/init.h>
  80#include <linux/ioport.h>
  81#include <linux/isapnp.h>
  82#include <linux/delay.h>
  83#include <linux/interrupt.h>
  84
  85#define NCR_NOT_SET 0
  86static int ncr_irq = NCR_NOT_SET;
  87static int ncr_dma = NCR_NOT_SET;
  88static int ncr_addr = NCR_NOT_SET;
  89static int ncr_5380 = NCR_NOT_SET;
  90static int ncr_53c400 = NCR_NOT_SET;
  91static int ncr_53c400a = NCR_NOT_SET;
  92static int dtc_3181e = NCR_NOT_SET;
  93
  94static struct override {
  95        NCR5380_map_type NCR5380_map_name;
  96        int irq;
  97        int dma;
  98        int board;              /* Use NCR53c400, Ricoh, etc. extensions ? */
  99} overrides
 100#ifdef GENERIC_NCR5380_OVERRIDE
 101[] __initdata = GENERIC_NCR5380_OVERRIDE;
 102#else
 103[1] __initdata = { { 0,},};
 104#endif
 105
 106#define NO_OVERRIDES ARRAY_SIZE(overrides)
 107
 108#ifndef MODULE
 109
 110/**
 111 *      internal_setup          -       handle lilo command string override
 112 *      @board: BOARD_* identifier for the board
 113 *      @str: unused
 114 *      @ints: numeric parameters
 115 *
 116 *      Do LILO command line initialization of the overrides array. Display
 117 *      errors when needed
 118 *
 119 *      Locks: none
 120 */
 121
 122static void __init internal_setup(int board, char *str, int *ints)
 123{
 124        static int commandline_current = 0;
 125        switch (board) {
 126        case BOARD_NCR5380:
 127                if (ints[0] != 2 && ints[0] != 3) {
 128                        printk(KERN_ERR "generic_NCR5380_setup : usage ncr5380=" STRVAL(NCR5380_map_name) ",irq,dma\n");
 129                        return;
 130                }
 131                break;
 132        case BOARD_NCR53C400:
 133                if (ints[0] != 2) {
 134                        printk(KERN_ERR "generic_NCR53C400_setup : usage ncr53c400=" STRVAL(NCR5380_map_name) ",irq\n");
 135                        return;
 136                }
 137                break;
 138        case BOARD_NCR53C400A:
 139                if (ints[0] != 2) {
 140                        printk(KERN_ERR "generic_NCR53C400A_setup : usage ncr53c400a=" STRVAL(NCR5380_map_name) ",irq\n");
 141                        return;
 142                }
 143                break;
 144        case BOARD_DTC3181E:
 145                if (ints[0] != 2) {
 146                        printk("generic_DTC3181E_setup : usage dtc3181e=" STRVAL(NCR5380_map_name) ",irq\n");
 147                        return;
 148                }
 149                break;
 150        }
 151
 152        if (commandline_current < NO_OVERRIDES) {
 153                overrides[commandline_current].NCR5380_map_name = (NCR5380_map_type) ints[1];
 154                overrides[commandline_current].irq = ints[2];
 155                if (ints[0] == 3)
 156                        overrides[commandline_current].dma = ints[3];
 157                else
 158                        overrides[commandline_current].dma = DMA_NONE;
 159                overrides[commandline_current].board = board;
 160                ++commandline_current;
 161        }
 162}
 163
 164
 165/**
 166 *      do_NCR53C80_setup               -       set up entry point
 167 *      @str: unused
 168 *
 169 *      Setup function invoked at boot to parse the ncr5380= command
 170 *      line.
 171 */
 172
 173static int __init do_NCR5380_setup(char *str)
 174{
 175        int ints[10];
 176
 177        get_options(str, ARRAY_SIZE(ints), ints);
 178        internal_setup(BOARD_NCR5380, str, ints);
 179        return 1;
 180}
 181
 182/**
 183 *      do_NCR53C400_setup              -       set up entry point
 184 *      @str: unused
 185 *      @ints: integer parameters from kernel setup code
 186 *
 187 *      Setup function invoked at boot to parse the ncr53c400= command
 188 *      line.
 189 */
 190
 191static int __init do_NCR53C400_setup(char *str)
 192{
 193        int ints[10];
 194
 195        get_options(str, ARRAY_SIZE(ints), ints);
 196        internal_setup(BOARD_NCR53C400, str, ints);
 197        return 1;
 198}
 199
 200/**
 201 *      do_NCR53C400A_setup     -       set up entry point
 202 *      @str: unused
 203 *      @ints: integer parameters from kernel setup code
 204 *
 205 *      Setup function invoked at boot to parse the ncr53c400a= command
 206 *      line.
 207 */
 208
 209static int __init do_NCR53C400A_setup(char *str)
 210{
 211        int ints[10];
 212
 213        get_options(str, ARRAY_SIZE(ints), ints);
 214        internal_setup(BOARD_NCR53C400A, str, ints);
 215        return 1;
 216}
 217
 218/**
 219 *      do_DTC3181E_setup       -       set up entry point
 220 *      @str: unused
 221 *      @ints: integer parameters from kernel setup code
 222 *
 223 *      Setup function invoked at boot to parse the dtc3181e= command
 224 *      line.
 225 */
 226
 227static int __init do_DTC3181E_setup(char *str)
 228{
 229        int ints[10];
 230
 231        get_options(str, ARRAY_SIZE(ints), ints);
 232        internal_setup(BOARD_DTC3181E, str, ints);
 233        return 1;
 234}
 235
 236#endif
 237
 238/**
 239 *      generic_NCR5380_detect  -       look for NCR5380 controllers
 240 *      @tpnt: the scsi template
 241 *
 242 *      Scan for the present of NCR5380, NCR53C400, NCR53C400A, DTC3181E
 243 *      and DTC436(ISAPnP) controllers. If overrides have been set we use
 244 *      them.
 245 *
 246 *      The caller supplied NCR5380_init function is invoked from here, before
 247 *      the interrupt line is taken.
 248 *
 249 *      Locks: none
 250 */
 251
 252static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
 253{
 254        static int current_override = 0;
 255        int count;
 256        unsigned int *ports;
 257#ifndef SCSI_G_NCR5380_MEM
 258        int i;
 259        unsigned long region_size = 16;
 260#endif
 261        static unsigned int __initdata ncr_53c400a_ports[] = {
 262                0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0
 263        };
 264        static unsigned int __initdata dtc_3181e_ports[] = {
 265                0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0
 266        };
 267        int flags = 0;
 268        struct Scsi_Host *instance;
 269#ifdef SCSI_G_NCR5380_MEM
 270        unsigned long base;
 271        void __iomem *iomem;
 272#endif
 273
 274        if (ncr_irq != NCR_NOT_SET)
 275                overrides[0].irq = ncr_irq;
 276        if (ncr_dma != NCR_NOT_SET)
 277                overrides[0].dma = ncr_dma;
 278        if (ncr_addr != NCR_NOT_SET)
 279                overrides[0].NCR5380_map_name = (NCR5380_map_type) ncr_addr;
 280        if (ncr_5380 != NCR_NOT_SET)
 281                overrides[0].board = BOARD_NCR5380;
 282        else if (ncr_53c400 != NCR_NOT_SET)
 283                overrides[0].board = BOARD_NCR53C400;
 284        else if (ncr_53c400a != NCR_NOT_SET)
 285                overrides[0].board = BOARD_NCR53C400A;
 286        else if (dtc_3181e != NCR_NOT_SET)
 287                overrides[0].board = BOARD_DTC3181E;
 288#ifndef SCSI_G_NCR5380_MEM
 289        if (!current_override && isapnp_present()) {
 290                struct pnp_dev *dev = NULL;
 291                count = 0;
 292                while ((dev = pnp_find_dev(NULL, ISAPNP_VENDOR('D', 'T', 'C'), ISAPNP_FUNCTION(0x436e), dev))) {
 293                        if (count >= NO_OVERRIDES)
 294                                break;
 295                        if (pnp_device_attach(dev) < 0)
 296                                continue;
 297                        if (pnp_activate_dev(dev) < 0) {
 298                                printk(KERN_ERR "dtc436e probe: activate failed\n");
 299                                pnp_device_detach(dev);
 300                                continue;
 301                        }
 302                        if (!pnp_port_valid(dev, 0)) {
 303                                printk(KERN_ERR "dtc436e probe: no valid port\n");
 304                                pnp_device_detach(dev);
 305                                continue;
 306                        }
 307                        if (pnp_irq_valid(dev, 0))
 308                                overrides[count].irq = pnp_irq(dev, 0);
 309                        else
 310                                overrides[count].irq = NO_IRQ;
 311                        if (pnp_dma_valid(dev, 0))
 312                                overrides[count].dma = pnp_dma(dev, 0);
 313                        else
 314                                overrides[count].dma = DMA_NONE;
 315                        overrides[count].NCR5380_map_name = (NCR5380_map_type) pnp_port_start(dev, 0);
 316                        overrides[count].board = BOARD_DTC3181E;
 317                        count++;
 318                }
 319        }
 320#endif
 321        tpnt->proc_name = "g_NCR5380";
 322
 323        for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
 324                if (!(overrides[current_override].NCR5380_map_name))
 325                        continue;
 326
 327                ports = NULL;
 328                switch (overrides[current_override].board) {
 329                case BOARD_NCR5380:
 330                        flags = FLAG_NO_PSEUDO_DMA;
 331                        break;
 332                case BOARD_NCR53C400:
 333                        flags = FLAG_NCR53C400;
 334                        break;
 335                case BOARD_NCR53C400A:
 336                        flags = FLAG_NO_PSEUDO_DMA;
 337                        ports = ncr_53c400a_ports;
 338                        break;
 339                case BOARD_DTC3181E:
 340                        flags = FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E;
 341                        ports = dtc_3181e_ports;
 342                        break;
 343                }
 344
 345#ifndef SCSI_G_NCR5380_MEM
 346                if (ports) {
 347                        /* wakeup sequence for the NCR53C400A and DTC3181E */
 348
 349                        /* Disable the adapter and look for a free io port */
 350                        outb(0x59, 0x779);
 351                        outb(0xb9, 0x379);
 352                        outb(0xc5, 0x379);
 353                        outb(0xae, 0x379);
 354                        outb(0xa6, 0x379);
 355                        outb(0x00, 0x379);
 356
 357                        if (overrides[current_override].NCR5380_map_name != PORT_AUTO)
 358                                for (i = 0; ports[i]; i++) {
 359                                        if (!request_region(ports[i],  16, "ncr53c80"))
 360                                                continue;
 361                                        if (overrides[current_override].NCR5380_map_name == ports[i])
 362                                                break;
 363                                        release_region(ports[i], 16);
 364                        } else
 365                                for (i = 0; ports[i]; i++) {
 366                                        if (!request_region(ports[i],  16, "ncr53c80"))
 367                                                continue;
 368                                        if (inb(ports[i]) == 0xff)
 369                                                break;
 370                                        release_region(ports[i], 16);
 371                                }
 372                        if (ports[i]) {
 373                                /* At this point we have our region reserved */
 374                                outb(0x59, 0x779);
 375                                outb(0xb9, 0x379);
 376                                outb(0xc5, 0x379);
 377                                outb(0xae, 0x379);
 378                                outb(0xa6, 0x379);
 379                                outb(0x80 | i, 0x379);  /* set io port to be used */
 380                                outb(0xc0, ports[i] + 9);
 381                                if (inb(ports[i] + 9) != 0x80)
 382                                        continue;
 383                                else
 384                                        overrides[current_override].NCR5380_map_name = ports[i];
 385                        } else
 386                                continue;
 387                }
 388                else
 389                {
 390                        /* Not a 53C400A style setup - just grab */
 391                        if(!(request_region(overrides[current_override].NCR5380_map_name, NCR5380_region_size, "ncr5380")))
 392                                continue;
 393                        region_size = NCR5380_region_size;
 394                }
 395#else
 396                base = overrides[current_override].NCR5380_map_name;
 397                if (!request_mem_region(base, NCR5380_region_size, "ncr5380"))
 398                        continue;
 399                iomem = ioremap(base, NCR5380_region_size);
 400                if (!iomem) {
 401                        release_mem_region(base, NCR5380_region_size);
 402                        continue;
 403                }
 404#endif
 405                instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
 406                if (instance == NULL) {
 407#ifndef SCSI_G_NCR5380_MEM
 408                        release_region(overrides[current_override].NCR5380_map_name, region_size);
 409#else
 410                        iounmap(iomem);
 411                        release_mem_region(base, NCR5380_region_size);
 412#endif
 413                        continue;
 414                }
 415
 416                instance->NCR5380_instance_name = overrides[current_override].NCR5380_map_name;
 417#ifndef SCSI_G_NCR5380_MEM
 418                instance->n_io_port = region_size;
 419#else
 420                ((struct NCR5380_hostdata *)instance->hostdata)->iomem = iomem;
 421#endif
 422
 423                NCR5380_init(instance, flags);
 424
 425                if (overrides[current_override].irq != IRQ_AUTO)
 426                        instance->irq = overrides[current_override].irq;
 427                else
 428                        instance->irq = NCR5380_probe_irq(instance, 0xffff);
 429
 430                /* Compatibility with documented NCR5380 kernel parameters */
 431                if (instance->irq == 255)
 432                        instance->irq = NO_IRQ;
 433
 434                if (instance->irq != NO_IRQ)
 435                        if (request_irq(instance->irq, generic_NCR5380_intr,
 436                                        0, "NCR5380", instance)) {
 437                                printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
 438                                instance->irq = NO_IRQ;
 439                        }
 440
 441                if (instance->irq == NO_IRQ) {
 442                        printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
 443                        printk(KERN_INFO "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
 444                }
 445
 446                ++current_override;
 447                ++count;
 448        }
 449        return count;
 450}
 451
 452/**
 453 *      generic_NCR5380_release_resources       -       free resources
 454 *      @instance: host adapter to clean up 
 455 *
 456 *      Free the generic interface resources from this adapter.
 457 *
 458 *      Locks: none
 459 */
 460 
 461static int generic_NCR5380_release_resources(struct Scsi_Host *instance)
 462{
 463        NCR5380_local_declare();
 464        NCR5380_setup(instance);
 465        
 466        if (instance->irq != NO_IRQ)
 467                free_irq(instance->irq, instance);
 468        NCR5380_exit(instance);
 469
 470#ifndef SCSI_G_NCR5380_MEM
 471        release_region(instance->NCR5380_instance_name, instance->n_io_port);
 472#else
 473        iounmap(((struct NCR5380_hostdata *)instance->hostdata)->iomem);
 474        release_mem_region(instance->NCR5380_instance_name, NCR5380_region_size);
 475#endif
 476
 477
 478        return 0;
 479}
 480
 481#ifdef BIOSPARAM
 482/**
 483 *      generic_NCR5380_biosparam
 484 *      @disk: disk to compute geometry for
 485 *      @dev: device identifier for this disk
 486 *      @ip: sizes to fill in
 487 *
 488 *      Generates a BIOS / DOS compatible H-C-S mapping for the specified 
 489 *      device / size.
 490 * 
 491 *      XXX Most SCSI boards use this mapping, I could be incorrect.  Someone
 492 *      using hard disks on a trantor should verify that this mapping
 493 *      corresponds to that used by the BIOS / ASPI driver by running the linux
 494 *      fdisk program and matching the H_C_S coordinates to what DOS uses.
 495 *
 496 *      Locks: none
 497 */
 498
 499static int
 500generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev,
 501                          sector_t capacity, int *ip)
 502{
 503        ip[0] = 64;
 504        ip[1] = 32;
 505        ip[2] = capacity >> 11;
 506        return 0;
 507}
 508#endif
 509
 510#ifdef NCR53C400_PSEUDO_DMA
 511
 512/**
 513 *      NCR5380_pread           -       pseudo DMA read
 514 *      @instance: adapter to read from
 515 *      @dst: buffer to read into
 516 *      @len: buffer length
 517 *
 518 *      Perform a pseudo DMA mode read from an NCR53C400 or equivalent
 519 *      controller
 520 */
 521 
 522static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len)
 523{
 524        int blocks = len / 128;
 525        int start = 0;
 526        int bl;
 527
 528        NCR5380_local_declare();
 529        NCR5380_setup(instance);
 530
 531        NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE | CSR_TRANS_DIR);
 532        NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
 533        while (1) {
 534                if ((bl = NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
 535                        break;
 536                }
 537                if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
 538                        printk(KERN_ERR "53C400r: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
 539                        return -1;
 540                }
 541                while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY);
 542
 543#ifndef SCSI_G_NCR5380_MEM
 544                {
 545                        int i;
 546                        for (i = 0; i < 128; i++)
 547                                dst[start + i] = NCR5380_read(C400_HOST_BUFFER);
 548                }
 549#else
 550                /* implies SCSI_G_NCR5380_MEM */
 551                memcpy_fromio(dst + start, iomem + NCR53C400_host_buffer, 128);
 552#endif
 553                start += 128;
 554                blocks--;
 555        }
 556
 557        if (blocks) {
 558                while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
 559                {
 560                        // FIXME - no timeout
 561                }
 562
 563#ifndef SCSI_G_NCR5380_MEM
 564                {
 565                        int i;  
 566                        for (i = 0; i < 128; i++)
 567                                dst[start + i] = NCR5380_read(C400_HOST_BUFFER);
 568                }
 569#else
 570                /* implies SCSI_G_NCR5380_MEM */
 571                memcpy_fromio(dst + start, iomem + NCR53C400_host_buffer, 128);
 572#endif
 573                start += 128;
 574                blocks--;
 575        }
 576
 577        if (!(NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
 578                printk("53C400r: no 53C80 gated irq after transfer");
 579
 580#if 0
 581        /*
 582         *      DON'T DO THIS - THEY NEVER ARRIVE!
 583         */
 584        printk("53C400r: Waiting for 53C80 registers\n");
 585        while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG)
 586                ;
 587#endif
 588        if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER))
 589                printk(KERN_ERR "53C400r: no end dma signal\n");
 590                
 591        NCR5380_write(MODE_REG, MR_BASE);
 592        NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 593        return 0;
 594}
 595
 596/**
 597 *      NCR5380_write           -       pseudo DMA write
 598 *      @instance: adapter to read from
 599 *      @dst: buffer to read into
 600 *      @len: buffer length
 601 *
 602 *      Perform a pseudo DMA mode read from an NCR53C400 or equivalent
 603 *      controller
 604 */
 605
 606static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len)
 607{
 608        int blocks = len / 128;
 609        int start = 0;
 610        int bl;
 611        int i;
 612
 613        NCR5380_local_declare();
 614        NCR5380_setup(instance);
 615
 616        NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
 617        NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
 618        while (1) {
 619                if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
 620                        printk(KERN_ERR "53C400w: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
 621                        return -1;
 622                }
 623
 624                if ((bl = NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
 625                        break;
 626                }
 627                while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
 628                        ; // FIXME - timeout
 629#ifndef SCSI_G_NCR5380_MEM
 630                {
 631                        for (i = 0; i < 128; i++)
 632                                NCR5380_write(C400_HOST_BUFFER, src[start + i]);
 633                }
 634#else
 635                /* implies SCSI_G_NCR5380_MEM */
 636                memcpy_toio(iomem + NCR53C400_host_buffer, src + start, 128);
 637#endif
 638                start += 128;
 639                blocks--;
 640        }
 641        if (blocks) {
 642                while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
 643                        ; // FIXME - no timeout
 644
 645#ifndef SCSI_G_NCR5380_MEM
 646                {
 647                        for (i = 0; i < 128; i++)
 648                                NCR5380_write(C400_HOST_BUFFER, src[start + i]);
 649                }
 650#else
 651                /* implies SCSI_G_NCR5380_MEM */
 652                memcpy_toio(iomem + NCR53C400_host_buffer, src + start, 128);
 653#endif
 654                start += 128;
 655                blocks--;
 656        }
 657
 658#if 0
 659        printk("53C400w: waiting for registers to be available\n");
 660        THEY NEVER DO ! while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG);
 661        printk("53C400w: Got em\n");
 662#endif
 663
 664        /* Let's wait for this instead - could be ugly */
 665        /* All documentation says to check for this. Maybe my hardware is too
 666         * fast. Waiting for it seems to work fine! KLL
 667         */
 668        while (!(i = NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
 669                ;       // FIXME - no timeout
 670
 671        /*
 672         * I know. i is certainly != 0 here but the loop is new. See previous
 673         * comment.
 674         */
 675        if (i) {
 676                if (!((i = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_END_DMA_TRANSFER))
 677                        printk(KERN_ERR "53C400w: No END OF DMA bit - WHOOPS! BASR=%0x\n", i);
 678        } else
 679                printk(KERN_ERR "53C400w: no 53C80 gated irq after transfer (last block)\n");
 680
 681#if 0
 682        if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) {
 683                printk(KERN_ERR "53C400w: no end dma signal\n");
 684        }
 685#endif
 686        while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT))
 687                ;       // TIMEOUT
 688        return 0;
 689}
 690#endif                          /* PSEUDO_DMA */
 691
 692/*
 693 *      Include the NCR5380 core code that we build our driver around   
 694 */
 695 
 696#include "NCR5380.c"
 697
 698static struct scsi_host_template driver_template = {
 699        .show_info              = generic_NCR5380_show_info,
 700        .name                   = "Generic NCR5380/NCR53C400 SCSI",
 701        .detect                 = generic_NCR5380_detect,
 702        .release                = generic_NCR5380_release_resources,
 703        .info                   = generic_NCR5380_info,
 704        .queuecommand           = generic_NCR5380_queue_command,
 705        .eh_abort_handler       = generic_NCR5380_abort,
 706        .eh_bus_reset_handler   = generic_NCR5380_bus_reset,
 707        .bios_param             = NCR5380_BIOSPARAM,
 708        .can_queue              = CAN_QUEUE,
 709        .this_id                = 7,
 710        .sg_tablesize           = SG_ALL,
 711        .cmd_per_lun            = CMD_PER_LUN,
 712        .use_clustering         = DISABLE_CLUSTERING,
 713};
 714#include <linux/module.h>
 715#include "scsi_module.c"
 716
 717module_param(ncr_irq, int, 0);
 718module_param(ncr_dma, int, 0);
 719module_param(ncr_addr, int, 0);
 720module_param(ncr_5380, int, 0);
 721module_param(ncr_53c400, int, 0);
 722module_param(ncr_53c400a, int, 0);
 723module_param(dtc_3181e, int, 0);
 724MODULE_LICENSE("GPL");
 725
 726#if !defined(SCSI_G_NCR5380_MEM) && defined(MODULE)
 727static struct isapnp_device_id id_table[] = {
 728        {
 729         ISAPNP_ANY_ID, ISAPNP_ANY_ID,
 730         ISAPNP_VENDOR('D', 'T', 'C'), ISAPNP_FUNCTION(0x436e),
 731         0},
 732        {0}
 733};
 734
 735MODULE_DEVICE_TABLE(isapnp, id_table);
 736#endif
 737
 738__setup("ncr5380=", do_NCR5380_setup);
 739__setup("ncr53c400=", do_NCR53C400_setup);
 740__setup("ncr53c400a=", do_NCR53C400A_setup);
 741__setup("dtc3181e=", do_DTC3181E_setup);
 742