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 * ALPHA RELEASE 1. 
  23 *
  24 * For more information, please consult 
  25 *
  26 * NCR 5380 Family
  27 * SCSI Protocol Controller
  28 * Databook
  29 *
  30 * NCR Microelectronics
  31 * 1635 Aeroplaza Drive
  32 * Colorado Springs, CO 80916
  33 * 1+ (719) 578-3400
  34 * 1+ (800) 334-5454
  35 */
  36
  37/* 
  38 * TODO : flesh out DMA support, find some one actually using this (I have
  39 *      a memory mapped Trantor board that works fine)
  40 */
  41
  42/*
  43 * Options :
  44 *
  45 * PARITY - enable parity checking.  Not supported.
  46 *
  47 * SCSI2 - enable support for SCSI-II tagged queueing.  Untested.
  48 *
  49 * USLEEP - enable support for devices that don't disconnect.  Untested.
  50 *
  51 * The card is detected and initialized in one of several ways : 
  52 * 1.  With command line overrides - NCR5380=port,irq may be 
  53 *     used on the LILO command line to override the defaults.
  54 *
  55 * 2.  With the GENERIC_NCR5380_OVERRIDE compile time define.  This is 
  56 *     specified as an array of address, irq, dma, board tuples.  Ie, for
  57 *     one board at 0x350, IRQ5, no dma, I could say  
  58 *     -DGENERIC_NCR5380_OVERRIDE={{0xcc000, 5, DMA_NONE, BOARD_NCR5380}}
  59 * 
  60 * -1 should be specified for no or DMA interrupt, -2 to autoprobe for an 
  61 *      IRQ line if overridden on the command line.
  62 *
  63 * 3.  When included as a module, with arguments passed on the command line:
  64 *         ncr_irq=xx   the interrupt
  65 *         ncr_addr=xx  the port or base address (for port or memory
  66 *                      mapped, resp.)
  67 *         ncr_dma=xx   the DMA
  68 *         ncr_5380=1   to set up for a NCR5380 board
  69 *         ncr_53c400=1 to set up for a NCR53C400 board
  70 *     e.g.
  71 *     modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_5380=1
  72 *       for a port mapped NCR5380 board or
  73 *     modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1
  74 *       for a memory mapped NCR53C400 board with interrupts disabled.
  75 * 
  76 * 255 should be specified for no or DMA interrupt, 254 to autoprobe for an 
  77 *      IRQ line if overridden on the command line.
  78 *     
  79 */
  80
  81/*
  82 * $Log: generic_NCR5380.c,v $
  83 */
  84
  85/* settings for DTC3181E card with only Mustek scanner attached */
  86#define USLEEP
  87#define USLEEP_POLL     1
  88#define USLEEP_SLEEP    20
  89#define USLEEP_WAITLONG 500
  90
  91#define AUTOPROBE_IRQ
  92#define AUTOSENSE
  93
  94
  95#ifdef CONFIG_SCSI_GENERIC_NCR53C400
  96#define NCR53C400_PSEUDO_DMA 1
  97#define PSEUDO_DMA
  98#define NCR53C400
  99#define NCR5380_STATS
 100#undef NCR5380_STAT_LIMIT
 101#endif
 102
 103#include <asm/io.h>
 104#include <linux/signal.h>
 105#include <linux/blkdev.h>
 106#include "scsi.h"
 107#include <scsi/scsi_host.h>
 108#include "g_NCR5380.h"
 109#include "NCR5380.h"
 110#include <linux/stat.h>
 111#include <linux/init.h>
 112#include <linux/ioport.h>
 113#include <linux/isapnp.h>
 114#include <linux/delay.h>
 115#include <linux/interrupt.h>
 116
 117#define NCR_NOT_SET 0
 118static int ncr_irq = NCR_NOT_SET;
 119static int ncr_dma = NCR_NOT_SET;
 120static int ncr_addr = NCR_NOT_SET;
 121static int ncr_5380 = NCR_NOT_SET;
 122static int ncr_53c400 = NCR_NOT_SET;
 123static int ncr_53c400a = NCR_NOT_SET;
 124static int dtc_3181e = NCR_NOT_SET;
 125
 126static struct override {
 127        NCR5380_map_type NCR5380_map_name;
 128        int irq;
 129        int dma;
 130        int board;              /* Use NCR53c400, Ricoh, etc. extensions ? */
 131} overrides
 132#ifdef GENERIC_NCR5380_OVERRIDE
 133[] __initdata = GENERIC_NCR5380_OVERRIDE;
 134#else
 135[1] __initdata = { { 0,},};
 136#endif
 137
 138#define NO_OVERRIDES ARRAY_SIZE(overrides)
 139
 140#ifndef MODULE
 141
 142/**
 143 *      internal_setup          -       handle lilo command string override
 144 *      @board: BOARD_* identifier for the board
 145 *      @str: unused
 146 *      @ints: numeric parameters
 147 *
 148 *      Do LILO command line initialization of the overrides array. Display
 149 *      errors when needed
 150 *
 151 *      Locks: none
 152 */
 153
 154static void __init internal_setup(int board, char *str, int *ints)
 155{
 156        static int commandline_current = 0;
 157        switch (board) {
 158        case BOARD_NCR5380:
 159                if (ints[0] != 2 && ints[0] != 3) {
 160                        printk(KERN_ERR "generic_NCR5380_setup : usage ncr5380=" STRVAL(NCR5380_map_name) ",irq,dma\n");
 161                        return;
 162                }
 163                break;
 164        case BOARD_NCR53C400:
 165                if (ints[0] != 2) {
 166                        printk(KERN_ERR "generic_NCR53C400_setup : usage ncr53c400=" STRVAL(NCR5380_map_name) ",irq\n");
 167                        return;
 168                }
 169                break;
 170        case BOARD_NCR53C400A:
 171                if (ints[0] != 2) {
 172                        printk(KERN_ERR "generic_NCR53C400A_setup : usage ncr53c400a=" STRVAL(NCR5380_map_name) ",irq\n");
 173                        return;
 174                }
 175                break;
 176        case BOARD_DTC3181E:
 177                if (ints[0] != 2) {
 178                        printk("generic_DTC3181E_setup : usage dtc3181e=" STRVAL(NCR5380_map_name) ",irq\n");
 179                        return;
 180                }
 181                break;
 182        }
 183
 184        if (commandline_current < NO_OVERRIDES) {
 185                overrides[commandline_current].NCR5380_map_name = (NCR5380_map_type) ints[1];
 186                overrides[commandline_current].irq = ints[2];
 187                if (ints[0] == 3)
 188                        overrides[commandline_current].dma = ints[3];
 189                else
 190                        overrides[commandline_current].dma = DMA_NONE;
 191                overrides[commandline_current].board = board;
 192                ++commandline_current;
 193        }
 194}
 195
 196
 197/**
 198 *      do_NCR53C80_setup               -       set up entry point
 199 *      @str: unused
 200 *
 201 *      Setup function invoked at boot to parse the ncr5380= command
 202 *      line.
 203 */
 204
 205static int __init do_NCR5380_setup(char *str)
 206{
 207        int ints[10];
 208
 209        get_options(str, ARRAY_SIZE(ints), ints);
 210        internal_setup(BOARD_NCR5380, str, ints);
 211        return 1;
 212}
 213
 214/**
 215 *      do_NCR53C400_setup              -       set up entry point
 216 *      @str: unused
 217 *      @ints: integer parameters from kernel setup code
 218 *
 219 *      Setup function invoked at boot to parse the ncr53c400= command
 220 *      line.
 221 */
 222
 223static int __init do_NCR53C400_setup(char *str)
 224{
 225        int ints[10];
 226
 227        get_options(str, ARRAY_SIZE(ints), ints);
 228        internal_setup(BOARD_NCR53C400, str, ints);
 229        return 1;
 230}
 231
 232/**
 233 *      do_NCR53C400A_setup     -       set up entry point
 234 *      @str: unused
 235 *      @ints: integer parameters from kernel setup code
 236 *
 237 *      Setup function invoked at boot to parse the ncr53c400a= command
 238 *      line.
 239 */
 240
 241static int __init do_NCR53C400A_setup(char *str)
 242{
 243        int ints[10];
 244
 245        get_options(str, ARRAY_SIZE(ints), ints);
 246        internal_setup(BOARD_NCR53C400A, str, ints);
 247        return 1;
 248}
 249
 250/**
 251 *      do_DTC3181E_setup       -       set up entry point
 252 *      @str: unused
 253 *      @ints: integer parameters from kernel setup code
 254 *
 255 *      Setup function invoked at boot to parse the dtc3181e= command
 256 *      line.
 257 */
 258
 259static int __init do_DTC3181E_setup(char *str)
 260{
 261        int ints[10];
 262
 263        get_options(str, ARRAY_SIZE(ints), ints);
 264        internal_setup(BOARD_DTC3181E, str, ints);
 265        return 1;
 266}
 267
 268#endif
 269
 270/**
 271 *      generic_NCR5380_detect  -       look for NCR5380 controllers
 272 *      @tpnt: the scsi template
 273 *
 274 *      Scan for the present of NCR5380, NCR53C400, NCR53C400A, DTC3181E
 275 *      and DTC436(ISAPnP) controllers. If overrides have been set we use
 276 *      them.
 277 *
 278 *      The caller supplied NCR5380_init function is invoked from here, before
 279 *      the interrupt line is taken.
 280 *
 281 *      Locks: none
 282 */
 283
 284int __init generic_NCR5380_detect(struct scsi_host_template * tpnt)
 285{
 286        static int current_override = 0;
 287        int count;
 288        unsigned int *ports;
 289#ifndef SCSI_G_NCR5380_MEM
 290        int i;
 291        unsigned long region_size = 16;
 292#endif
 293        static unsigned int __initdata ncr_53c400a_ports[] = {
 294                0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0
 295        };
 296        static unsigned int __initdata dtc_3181e_ports[] = {
 297                0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0
 298        };
 299        int flags = 0;
 300        struct Scsi_Host *instance;
 301#ifdef SCSI_G_NCR5380_MEM
 302        unsigned long base;
 303        void __iomem *iomem;
 304#endif
 305
 306        if (ncr_irq != NCR_NOT_SET)
 307                overrides[0].irq = ncr_irq;
 308        if (ncr_dma != NCR_NOT_SET)
 309                overrides[0].dma = ncr_dma;
 310        if (ncr_addr != NCR_NOT_SET)
 311                overrides[0].NCR5380_map_name = (NCR5380_map_type) ncr_addr;
 312        if (ncr_5380 != NCR_NOT_SET)
 313                overrides[0].board = BOARD_NCR5380;
 314        else if (ncr_53c400 != NCR_NOT_SET)
 315                overrides[0].board = BOARD_NCR53C400;
 316        else if (ncr_53c400a != NCR_NOT_SET)
 317                overrides[0].board = BOARD_NCR53C400A;
 318        else if (dtc_3181e != NCR_NOT_SET)
 319                overrides[0].board = BOARD_DTC3181E;
 320#ifndef SCSI_G_NCR5380_MEM
 321        if (!current_override && isapnp_present()) {
 322                struct pnp_dev *dev = NULL;
 323                count = 0;
 324                while ((dev = pnp_find_dev(NULL, ISAPNP_VENDOR('D', 'T', 'C'), ISAPNP_FUNCTION(0x436e), dev))) {
 325                        if (count >= NO_OVERRIDES)
 326                                break;
 327                        if (pnp_device_attach(dev) < 0)
 328                                continue;
 329                        if (pnp_activate_dev(dev) < 0) {
 330                                printk(KERN_ERR "dtc436e probe: activate failed\n");
 331                                pnp_device_detach(dev);
 332                                continue;
 333                        }
 334                        if (!pnp_port_valid(dev, 0)) {
 335                                printk(KERN_ERR "dtc436e probe: no valid port\n");
 336                                pnp_device_detach(dev);
 337                                continue;
 338                        }
 339                        if (pnp_irq_valid(dev, 0))
 340                                overrides[count].irq = pnp_irq(dev, 0);
 341                        else
 342                                overrides[count].irq = SCSI_IRQ_NONE;
 343                        if (pnp_dma_valid(dev, 0))
 344                                overrides[count].dma = pnp_dma(dev, 0);
 345                        else
 346                                overrides[count].dma = DMA_NONE;
 347                        overrides[count].NCR5380_map_name = (NCR5380_map_type) pnp_port_start(dev, 0);
 348                        overrides[count].board = BOARD_DTC3181E;
 349                        count++;
 350                }
 351        }
 352#endif
 353        tpnt->proc_name = "g_NCR5380";
 354
 355        for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
 356                if (!(overrides[current_override].NCR5380_map_name))
 357                        continue;
 358
 359                ports = NULL;
 360                switch (overrides[current_override].board) {
 361                case BOARD_NCR5380:
 362                        flags = FLAG_NO_PSEUDO_DMA;
 363                        break;
 364                case BOARD_NCR53C400:
 365                        flags = FLAG_NCR53C400;
 366                        break;
 367                case BOARD_NCR53C400A:
 368                        flags = FLAG_NO_PSEUDO_DMA;
 369                        ports = ncr_53c400a_ports;
 370                        break;
 371                case BOARD_DTC3181E:
 372                        flags = FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E;
 373                        ports = dtc_3181e_ports;
 374                        break;
 375                }
 376
 377#ifndef SCSI_G_NCR5380_MEM
 378                if (ports) {
 379                        /* wakeup sequence for the NCR53C400A and DTC3181E */
 380
 381                        /* Disable the adapter and look for a free io port */
 382                        outb(0x59, 0x779);
 383                        outb(0xb9, 0x379);
 384                        outb(0xc5, 0x379);
 385                        outb(0xae, 0x379);
 386                        outb(0xa6, 0x379);
 387                        outb(0x00, 0x379);
 388
 389                        if (overrides[current_override].NCR5380_map_name != PORT_AUTO)
 390                                for (i = 0; ports[i]; i++) {
 391                                        if (!request_region(ports[i],  16, "ncr53c80"))
 392                                                continue;
 393                                        if (overrides[current_override].NCR5380_map_name == ports[i])
 394                                                break;
 395                                        release_region(ports[i], 16);
 396                        } else
 397                                for (i = 0; ports[i]; i++) {
 398                                        if (!request_region(ports[i],  16, "ncr53c80"))
 399                                                continue;
 400                                        if (inb(ports[i]) == 0xff)
 401                                                break;
 402                                        release_region(ports[i], 16);
 403                                }
 404                        if (ports[i]) {
 405                                /* At this point we have our region reserved */
 406                                outb(0x59, 0x779);
 407                                outb(0xb9, 0x379);
 408                                outb(0xc5, 0x379);
 409                                outb(0xae, 0x379);
 410                                outb(0xa6, 0x379);
 411                                outb(0x80 | i, 0x379);  /* set io port to be used */
 412                                outb(0xc0, ports[i] + 9);
 413                                if (inb(ports[i] + 9) != 0x80)
 414                                        continue;
 415                                else
 416                                        overrides[current_override].NCR5380_map_name = ports[i];
 417                        } else
 418                                continue;
 419                }
 420                else
 421                {
 422                        /* Not a 53C400A style setup - just grab */
 423                        if(!(request_region(overrides[current_override].NCR5380_map_name, NCR5380_region_size, "ncr5380")))
 424                                continue;
 425                        region_size = NCR5380_region_size;
 426                }
 427#else
 428                base = overrides[current_override].NCR5380_map_name;
 429                if (!request_mem_region(base, NCR5380_region_size, "ncr5380"))
 430                        continue;
 431                iomem = ioremap(base, NCR5380_region_size);
 432                if (!iomem) {
 433                        release_mem_region(base, NCR5380_region_size);
 434                        continue;
 435                }
 436#endif
 437                instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
 438                if (instance == NULL) {
 439#ifndef SCSI_G_NCR5380_MEM
 440                        release_region(overrides[current_override].NCR5380_map_name, region_size);
 441#else
 442                        iounmap(iomem);
 443                        release_mem_region(base, NCR5380_region_size);
 444#endif
 445                        continue;
 446                }
 447
 448                instance->NCR5380_instance_name = overrides[current_override].NCR5380_map_name;
 449#ifndef SCSI_G_NCR5380_MEM
 450                instance->n_io_port = region_size;
 451#else
 452                ((struct NCR5380_hostdata *)instance->hostdata)->iomem = iomem;
 453#endif
 454
 455                NCR5380_init(instance, flags);
 456
 457                if (overrides[current_override].irq != IRQ_AUTO)
 458                        instance->irq = overrides[current_override].irq;
 459                else
 460                        instance->irq = NCR5380_probe_irq(instance, 0xffff);
 461
 462                if (instance->irq != SCSI_IRQ_NONE)
 463                        if (request_irq(instance->irq, generic_NCR5380_intr,
 464                                        IRQF_DISABLED, "NCR5380", instance)) {
 465                                printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
 466                                instance->irq = SCSI_IRQ_NONE;
 467                        }
 468
 469                if (instance->irq == SCSI_IRQ_NONE) {
 470                        printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
 471                        printk(KERN_INFO "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
 472                }
 473
 474                printk(KERN_INFO "scsi%d : at " STRVAL(NCR5380_map_name) " 0x%x", instance->host_no, (unsigned int) instance->NCR5380_instance_name);
 475                if (instance->irq == SCSI_IRQ_NONE)
 476                        printk(" interrupts disabled");
 477                else
 478                        printk(" irq %d", instance->irq);
 479                printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d", CAN_QUEUE, CMD_PER_LUN, GENERIC_NCR5380_PUBLIC_RELEASE);
 480                NCR5380_print_options(instance);
 481                printk("\n");
 482
 483                ++current_override;
 484                ++count;
 485        }
 486        return count;
 487}
 488
 489/**
 490 *      generic_NCR5380_info    -       reporting string
 491 *      @host: NCR5380 to report on
 492 *
 493 *      Report driver information for the NCR5380
 494 */
 495        
 496const char *generic_NCR5380_info(struct Scsi_Host *host)
 497{
 498        static const char string[] = "Generic NCR5380/53C400 Driver";
 499        return string;
 500}
 501
 502/**
 503 *      generic_NCR5380_release_resources       -       free resources
 504 *      @instance: host adapter to clean up 
 505 *
 506 *      Free the generic interface resources from this adapter.
 507 *
 508 *      Locks: none
 509 */
 510 
 511int generic_NCR5380_release_resources(struct Scsi_Host *instance)
 512{
 513        NCR5380_local_declare();
 514        NCR5380_setup(instance);
 515        
 516        if (instance->irq != SCSI_IRQ_NONE)
 517                free_irq(instance->irq, instance);
 518        NCR5380_exit(instance);
 519
 520#ifndef SCSI_G_NCR5380_MEM
 521        release_region(instance->NCR5380_instance_name, instance->n_io_port);
 522#else
 523        iounmap(((struct NCR5380_hostdata *)instance->hostdata)->iomem);
 524        release_mem_region(instance->NCR5380_instance_name, NCR5380_region_size);
 525#endif
 526
 527
 528        return 0;
 529}
 530
 531#ifdef BIOSPARAM
 532/**
 533 *      generic_NCR5380_biosparam
 534 *      @disk: disk to compute geometry for
 535 *      @dev: device identifier for this disk
 536 *      @ip: sizes to fill in
 537 *
 538 *      Generates a BIOS / DOS compatible H-C-S mapping for the specified 
 539 *      device / size.
 540 * 
 541 *      XXX Most SCSI boards use this mapping, I could be incorrect.  Someone
 542 *      using hard disks on a trantor should verify that this mapping
 543 *      corresponds to that used by the BIOS / ASPI driver by running the linux
 544 *      fdisk program and matching the H_C_S coordinates to what DOS uses.
 545 *
 546 *      Locks: none
 547 */
 548
 549static int
 550generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev,
 551                          sector_t capacity, int *ip)
 552{
 553        ip[0] = 64;
 554        ip[1] = 32;
 555        ip[2] = capacity >> 11;
 556        return 0;
 557}
 558#endif
 559
 560#ifdef NCR53C400_PSEUDO_DMA
 561
 562/**
 563 *      NCR5380_pread           -       pseudo DMA read
 564 *      @instance: adapter to read from
 565 *      @dst: buffer to read into
 566 *      @len: buffer length
 567 *
 568 *      Perform a pseudo DMA mode read from an NCR53C400 or equivalent
 569 *      controller
 570 */
 571 
 572static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len)
 573{
 574        int blocks = len / 128;
 575        int start = 0;
 576        int bl;
 577
 578        NCR5380_local_declare();
 579        NCR5380_setup(instance);
 580
 581        NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE | CSR_TRANS_DIR);
 582        NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
 583        while (1) {
 584                if ((bl = NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
 585                        break;
 586                }
 587                if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
 588                        printk(KERN_ERR "53C400r: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
 589                        return -1;
 590                }
 591                while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY);
 592
 593#ifndef SCSI_G_NCR5380_MEM
 594                {
 595                        int i;
 596                        for (i = 0; i < 128; i++)
 597                                dst[start + i] = NCR5380_read(C400_HOST_BUFFER);
 598                }
 599#else
 600                /* implies SCSI_G_NCR5380_MEM */
 601                memcpy_fromio(dst + start, iomem + NCR53C400_host_buffer, 128);
 602#endif
 603                start += 128;
 604                blocks--;
 605        }
 606
 607        if (blocks) {
 608                while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
 609                {
 610                        // FIXME - no timeout
 611                }
 612
 613#ifndef SCSI_G_NCR5380_MEM
 614                {
 615                        int i;  
 616                        for (i = 0; i < 128; i++)
 617                                dst[start + i] = NCR5380_read(C400_HOST_BUFFER);
 618                }
 619#else
 620                /* implies SCSI_G_NCR5380_MEM */
 621                memcpy_fromio(dst + start, iomem + NCR53C400_host_buffer, 128);
 622#endif
 623                start += 128;
 624                blocks--;
 625        }
 626
 627        if (!(NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
 628                printk("53C400r: no 53C80 gated irq after transfer");
 629
 630#if 0
 631        /*
 632         *      DON'T DO THIS - THEY NEVER ARRIVE!
 633         */
 634        printk("53C400r: Waiting for 53C80 registers\n");
 635        while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG)
 636                ;
 637#endif
 638        if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER))
 639                printk(KERN_ERR "53C400r: no end dma signal\n");
 640                
 641        NCR5380_write(MODE_REG, MR_BASE);
 642        NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 643        return 0;
 644}
 645
 646/**
 647 *      NCR5380_write           -       pseudo DMA write
 648 *      @instance: adapter to read from
 649 *      @dst: buffer to read into
 650 *      @len: buffer length
 651 *
 652 *      Perform a pseudo DMA mode read from an NCR53C400 or equivalent
 653 *      controller
 654 */
 655
 656static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len)
 657{
 658        int blocks = len / 128;
 659        int start = 0;
 660        int bl;
 661        int i;
 662
 663        NCR5380_local_declare();
 664        NCR5380_setup(instance);
 665
 666        NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
 667        NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
 668        while (1) {
 669                if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
 670                        printk(KERN_ERR "53C400w: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
 671                        return -1;
 672                }
 673
 674                if ((bl = NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
 675                        break;
 676                }
 677                while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
 678                        ; // FIXME - timeout
 679#ifndef SCSI_G_NCR5380_MEM
 680                {
 681                        for (i = 0; i < 128; i++)
 682                                NCR5380_write(C400_HOST_BUFFER, src[start + i]);
 683                }
 684#else
 685                /* implies SCSI_G_NCR5380_MEM */
 686                memcpy_toio(iomem + NCR53C400_host_buffer, src + start, 128);
 687#endif
 688                start += 128;
 689                blocks--;
 690        }
 691        if (blocks) {
 692                while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
 693                        ; // FIXME - no timeout
 694
 695#ifndef SCSI_G_NCR5380_MEM
 696                {
 697                        for (i = 0; i < 128; i++)
 698                                NCR5380_write(C400_HOST_BUFFER, src[start + i]);
 699                }
 700#else
 701                /* implies SCSI_G_NCR5380_MEM */
 702                memcpy_toio(iomem + NCR53C400_host_buffer, src + start, 128);
 703#endif
 704                start += 128;
 705                blocks--;
 706        }
 707
 708#if 0
 709        printk("53C400w: waiting for registers to be available\n");
 710        THEY NEVER DO ! while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG);
 711        printk("53C400w: Got em\n");
 712#endif
 713
 714        /* Let's wait for this instead - could be ugly */
 715        /* All documentation says to check for this. Maybe my hardware is too
 716         * fast. Waiting for it seems to work fine! KLL
 717         */
 718        while (!(i = NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
 719                ;       // FIXME - no timeout
 720
 721        /*
 722         * I know. i is certainly != 0 here but the loop is new. See previous
 723         * comment.
 724         */
 725        if (i) {
 726                if (!((i = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_END_DMA_TRANSFER))
 727                        printk(KERN_ERR "53C400w: No END OF DMA bit - WHOOPS! BASR=%0x\n", i);
 728        } else
 729                printk(KERN_ERR "53C400w: no 53C80 gated irq after transfer (last block)\n");
 730
 731#if 0
 732        if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) {
 733                printk(KERN_ERR "53C400w: no end dma signal\n");
 734        }
 735#endif
 736        while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT))
 737                ;       // TIMEOUT
 738        return 0;
 739}
 740#endif                          /* PSEUDO_DMA */
 741
 742/*
 743 *      Include the NCR5380 core code that we build our driver around   
 744 */
 745 
 746#include "NCR5380.c"
 747
 748#define PRINTP(x) len += sprintf(buffer+len, x)
 749#define ANDP ,
 750
 751static int sprint_opcode(char *buffer, int len, int opcode)
 752{
 753        int start = len;
 754        PRINTP("0x%02x " ANDP opcode);
 755        return len - start;
 756}
 757
 758static int sprint_command(char *buffer, int len, unsigned char *command)
 759{
 760        int i, s, start = len;
 761        len += sprint_opcode(buffer, len, command[0]);
 762        for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
 763                PRINTP("%02x " ANDP command[i]);
 764        PRINTP("\n");
 765        return len - start;
 766}
 767
 768/**
 769 *      sprintf_Scsi_Cmnd       -       print a scsi command
 770 *      @buffer: buffr to print into
 771 *      @len: buffer length
 772 *      @cmd: SCSI command block
 773 *      
 774 *      Print out the target and command data in hex
 775 */
 776
 777static int sprint_Scsi_Cmnd(char *buffer, int len, Scsi_Cmnd * cmd)
 778{
 779        int start = len;
 780        PRINTP("host number %d destination target %d, lun %d\n" ANDP cmd->device->host->host_no ANDP cmd->device->id ANDP cmd->device->lun);
 781        PRINTP("        command = ");
 782        len += sprint_command(buffer, len, cmd->cmnd);
 783        return len - start;
 784}
 785
 786/**
 787 *      generic_NCR5380_proc_info       -       /proc for NCR5380 driver
 788 *      @buffer: buffer to print into
 789 *      @start: start position
 790 *      @offset: offset into buffer
 791 *      @len: length
 792 *      @hostno: instance to affect
 793 *      @inout: read/write
 794 *
 795 *      Provide the procfs information for the 5380 controller. We fill
 796 *      this with useful debugging information including the commands
 797 *      being executed, disconnected command queue and the statistical
 798 *      data
 799 *
 800 *      Locks: global cli/lock for queue walk
 801 */
 802 
 803static int generic_NCR5380_proc_info(struct Scsi_Host *scsi_ptr, char *buffer, char **start, off_t offset, int length, int inout)
 804{
 805        int len = 0;
 806        NCR5380_local_declare();
 807        unsigned long flags;
 808        unsigned char status;
 809        int i;
 810        Scsi_Cmnd *ptr;
 811        struct NCR5380_hostdata *hostdata;
 812#ifdef NCR5380_STATS
 813        struct scsi_device *dev;
 814#endif
 815
 816        NCR5380_setup(scsi_ptr);
 817        hostdata = (struct NCR5380_hostdata *) scsi_ptr->hostdata;
 818
 819        spin_lock_irqsave(scsi_ptr->host_lock, flags);
 820        PRINTP("SCSI host number %d : %s\n" ANDP scsi_ptr->host_no ANDP scsi_ptr->hostt->name);
 821        PRINTP("Generic NCR5380 driver version %d\n" ANDP GENERIC_NCR5380_PUBLIC_RELEASE);
 822        PRINTP("NCR5380 core version %d\n" ANDP NCR5380_PUBLIC_RELEASE);
 823#ifdef NCR53C400
 824        PRINTP("NCR53C400 extension version %d\n" ANDP NCR53C400_PUBLIC_RELEASE);
 825        PRINTP("NCR53C400 card%s detected\n" ANDP(((struct NCR5380_hostdata *) scsi_ptr->hostdata)->flags & FLAG_NCR53C400) ? "" : " not");
 826# if NCR53C400_PSEUDO_DMA
 827        PRINTP("NCR53C400 pseudo DMA used\n");
 828# endif
 829#else
 830        PRINTP("NO NCR53C400 driver extensions\n");
 831#endif
 832        PRINTP("Using %s mapping at %s 0x%lx, " ANDP STRVAL(NCR5380_map_config) ANDP STRVAL(NCR5380_map_name) ANDP scsi_ptr->NCR5380_instance_name);
 833        if (scsi_ptr->irq == SCSI_IRQ_NONE)
 834                PRINTP("no interrupt\n");
 835        else
 836                PRINTP("on interrupt %d\n" ANDP scsi_ptr->irq);
 837
 838#ifdef NCR5380_STATS
 839        if (hostdata->connected || hostdata->issue_queue || hostdata->disconnected_queue)
 840                PRINTP("There are commands pending, transfer rates may be crud\n");
 841        if (hostdata->pendingr)
 842                PRINTP("  %d pending reads" ANDP hostdata->pendingr);
 843        if (hostdata->pendingw)
 844                PRINTP("  %d pending writes" ANDP hostdata->pendingw);
 845        if (hostdata->pendingr || hostdata->pendingw)
 846                PRINTP("\n");
 847        shost_for_each_device(dev, scsi_ptr) {
 848                unsigned long br = hostdata->bytes_read[dev->id];
 849                unsigned long bw = hostdata->bytes_write[dev->id];
 850                long tr = hostdata->time_read[dev->id] / HZ;
 851                long tw = hostdata->time_write[dev->id] / HZ;
 852
 853                PRINTP("  T:%d %s " ANDP dev->id ANDP scsi_device_type(dev->type));
 854                for (i = 0; i < 8; i++)
 855                        if (dev->vendor[i] >= 0x20)
 856                                *(buffer + (len++)) = dev->vendor[i];
 857                *(buffer + (len++)) = ' ';
 858                for (i = 0; i < 16; i++)
 859                        if (dev->model[i] >= 0x20)
 860                                *(buffer + (len++)) = dev->model[i];
 861                *(buffer + (len++)) = ' ';
 862                for (i = 0; i < 4; i++)
 863                        if (dev->rev[i] >= 0x20)
 864                                *(buffer + (len++)) = dev->rev[i];
 865                *(buffer + (len++)) = ' ';
 866
 867                PRINTP("\n%10ld kb read    in %5ld secs" ANDP br / 1024 ANDP tr);
 868                if (tr)
 869                        PRINTP(" @ %5ld bps" ANDP br / tr);
 870
 871                PRINTP("\n%10ld kb written in %5ld secs" ANDP bw / 1024 ANDP tw);
 872                if (tw)
 873                        PRINTP(" @ %5ld bps" ANDP bw / tw);
 874                PRINTP("\n");
 875        }
 876#endif
 877
 878        status = NCR5380_read(STATUS_REG);
 879        if (!(status & SR_REQ))
 880                PRINTP("REQ not asserted, phase unknown.\n");
 881        else {
 882                for (i = 0; (phases[i].value != PHASE_UNKNOWN) && (phases[i].value != (status & PHASE_MASK)); ++i);
 883                PRINTP("Phase %s\n" ANDP phases[i].name);
 884        }
 885
 886        if (!hostdata->connected) {
 887                PRINTP("No currently connected command\n");
 888        } else {
 889                len += sprint_Scsi_Cmnd(buffer, len, (Scsi_Cmnd *) hostdata->connected);
 890        }
 891
 892        PRINTP("issue_queue\n");
 893
 894        for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
 895                len += sprint_Scsi_Cmnd(buffer, len, ptr);
 896
 897        PRINTP("disconnected_queue\n");
 898
 899        for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
 900                len += sprint_Scsi_Cmnd(buffer, len, ptr);
 901
 902        *start = buffer + offset;
 903        len -= offset;
 904        if (len > length)
 905                len = length;
 906        spin_unlock_irqrestore(scsi_ptr->host_lock, flags);
 907        return len;
 908}
 909
 910#undef PRINTP
 911#undef ANDP
 912
 913static struct scsi_host_template driver_template = {
 914        .proc_info              = generic_NCR5380_proc_info,
 915        .name                   = "Generic NCR5380/NCR53C400 Scsi Driver",
 916        .detect                 = generic_NCR5380_detect,
 917        .release                = generic_NCR5380_release_resources,
 918        .info                   = generic_NCR5380_info,
 919        .queuecommand           = generic_NCR5380_queue_command,
 920        .eh_abort_handler       = generic_NCR5380_abort,
 921        .eh_bus_reset_handler   = generic_NCR5380_bus_reset,
 922        .bios_param             = NCR5380_BIOSPARAM,
 923        .can_queue              = CAN_QUEUE,
 924        .this_id                = 7,
 925        .sg_tablesize           = SG_ALL,
 926        .cmd_per_lun            = CMD_PER_LUN,
 927        .use_clustering         = DISABLE_CLUSTERING,
 928};
 929#include <linux/module.h>
 930#include "scsi_module.c"
 931
 932module_param(ncr_irq, int, 0);
 933module_param(ncr_dma, int, 0);
 934module_param(ncr_addr, int, 0);
 935module_param(ncr_5380, int, 0);
 936module_param(ncr_53c400, int, 0);
 937module_param(ncr_53c400a, int, 0);
 938module_param(dtc_3181e, int, 0);
 939MODULE_LICENSE("GPL");
 940
 941#ifndef SCSI_G_NCR5380_MEM
 942static struct isapnp_device_id id_table[] __devinitdata = {
 943        {
 944         ISAPNP_ANY_ID, ISAPNP_ANY_ID,
 945         ISAPNP_VENDOR('D', 'T', 'C'), ISAPNP_FUNCTION(0x436e),
 946         0},
 947        {0}
 948};
 949
 950MODULE_DEVICE_TABLE(isapnp, id_table);
 951#endif
 952
 953__setup("ncr5380=", do_NCR5380_setup);
 954__setup("ncr53c400=", do_NCR53C400_setup);
 955__setup("ncr53c400a=", do_NCR53C400A_setup);
 956__setup("dtc3181e=", do_DTC3181E_setup);
 957
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.