root/drivers/scsi/dtc.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dtc_detect
  2. dtc_biosparam
  3. NCR5380_pread
  4. NCR5380_pwrite

   1 
   2 #define AUTOSENSE
   3 #define PSEUDO_DMA
   4 #define DONT_USE_INTR
   5 #define UNSAFE          /* Leave interrupts enabled during pseudo-dma I/O */
   6 #define xNDEBUG (NDEBUG_INTR+NDEBUG_RESELECTION+\
   7                  NDEBUG_SELECTION+NDEBUG_ARBITRATION)
   8 #define DMA_WORKS_RIGHT
   9 
  10 
  11 /*
  12  * DTC 3180/3280 driver, by
  13  *      Ray Van Tassle  rayvt@comm.mot.com
  14  *
  15  *      taken from ...
  16  *      Trantor T128/T128F/T228 driver by...
  17  *
  18  *      Drew Eckhardt
  19  *      Visionary Computing
  20  *      (Unix and Linux consulting and custom programming)
  21  *      drew@colorado.edu
  22  *      +1 (303) 440-4894
  23  *
  24  * DISTRIBUTION RELEASE 1.
  25  *
  26  * For more information, please consult 
  27  *
  28  * NCR 5380 Family
  29  * SCSI Protocol Controller
  30  * Databook
  31 */
  32 
  33 /*
  34  * Options : 
  35  * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
  36  *      for commands that return with a CHECK CONDITION status. 
  37  *
  38  * PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance
  39  * increase compared to polled I/O.
  40  *
  41  * PARITY - enable parity checking.  Not supported.
  42  *
  43  * UNSAFE - leave interrupts enabled during pseudo-DMA transfers. 
  44  *              You probably want this.
  45  *
  46  * The card is detected and initialized in one of several ways : 
  47  * 1.  Autoprobe (default) - since the board is memory mapped, 
  48  *     a BIOS signature is scanned for to locate the registers.
  49  *     An interrupt is triggered to autoprobe for the interrupt
  50  *     line.
  51  *
  52  * 2.  With command line overrides - dtc=address,irq may be 
  53  *     used on the LILO command line to override the defaults.
  54  * 
  55 */
  56 
  57 /*----------------------------------------------------------------*/
  58 /* the following will set the monitor border color (useful to find
  59  where something crashed or gets stuck at */
  60 /* 1 = blue
  61  2 = green
  62  3 = cyan
  63  4 = red
  64  5 = magenta
  65  6 = yellow
  66  7 = white
  67 */
  68 #if 0
  69 #define rtrc(i) {inb(0x3da); outb(0x31, 0x3c0); outb((i), 0x3c0);}
  70 #else
  71 #define rtrc(i) {}
  72 #endif
  73 
  74 
  75 #include <asm/system.h>
  76 #include <linux/signal.h>
  77 #include <linux/sched.h>
  78 #include <linux/blk.h>
  79 #include <asm/io.h>
  80 #include "scsi.h"
  81 #include "hosts.h"
  82 #include "dtc.h"
  83 #define AUTOPROBE_IRQ
  84 #include "NCR5380.h"
  85 #include "constants.h"
  86 #include "sd.h"
  87 #include<linux/stat.h>
  88 #include<linux/string.h>
  89 
  90 struct proc_dir_entry proc_scsi_dtc = {
  91    PROC_SCSI_T128, 7, "dtc3x80",
  92         S_IFDIR | S_IRUGO | S_IXUGO, 2
  93      };
  94 
  95 
  96 static struct override {
  97    unsigned char *address;
  98    int irq;
  99 } overrides
 100 #ifdef OVERRIDE
 101 [] = OVERRIDE;
 102 #else
 103 [4] = {{NULL, IRQ_AUTO}, {NULL, IRQ_AUTO}, {NULL, IRQ_AUTO},
 104      {NULL, IRQ_AUTO}};
 105 #endif
 106 
 107 #define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
 108 
 109 static struct base {
 110    unsigned char *address;
 111    int noauto;
 112 } bases[] = {{(unsigned char *) 0xcc000, 0}, {(unsigned char *) 0xc8000, 0},
 113 {(unsigned char *) 0xdc000, 0}, {(unsigned char *) 0xd8000, 0}};
 114 
 115 #define NO_BASES (sizeof (bases) / sizeof (struct base))
 116 
 117 static const struct signature {
 118    const char *string;
 119    int offset;
 120 } signatures[] = { {"DATA TECHNOLOGY CORPORATION BIOS", 0x25}, };
 121 
 122 #define NO_SIGNATURES (sizeof (signatures) /  sizeof (struct signature))
 123 
 124 /*
 125  * Function : dtc_setup(char *str, int *ints)
 126  *
 127  * Purpose : LILO command line initialization of the overrides array,
 128  * 
 129  * Inputs : str - unused, ints - array of integer parameters with ints[0]
 130  *      equal to the number of ints.
 131  *
 132 */
 133 
 134 void dtc_setup(char *str, int *ints) {
 135    static int commandline_current = 0;
 136    int i;
 137    if (ints[0] != 2)
 138       printk("dtc_setup: usage dtc=address,irq\n");
 139    else
 140       if (commandline_current < NO_OVERRIDES) {
 141       overrides[commandline_current].address = (unsigned char *) ints[1];
 142       overrides[commandline_current].irq = ints[2];
 143       for (i = 0; i < NO_BASES; ++i)
 144          if (bases[i].address == (unsigned char *) ints[1]) {
 145          bases[i].noauto = 1;
 146          break;
 147       }
 148       ++commandline_current;
 149    }
 150 }
 151 
 152 /* 
 153  * Function : int dtc_detect(Scsi_Host_Template * tpnt)
 154  *
 155  * Purpose : detects and initializes DTC 3180/3280 controllers
 156  *      that were autoprobed, overridden on the LILO command line, 
 157  *      or specified at compile time.
 158  *
 159  * Inputs : tpnt - template for this SCSI adapter.
 160  * 
 161  * Returns : 1 if a host adapter was found, 0 if not.
 162  *
 163 */
 164 
 165 
 166 int dtc_detect(Scsi_Host_Template * tpnt) {
     /* [previous][next][first][last][top][bottom][index][help] */
 167    static int current_override = 0, current_base = 0;
 168    struct Scsi_Host *instance;
 169    unsigned char *base;
 170    int sig, count;
 171 
 172    tpnt->proc_dir = &proc_scsi_dtc;
 173    tpnt->proc_info = &dtc_proc_info;
 174 
 175    for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
 176       base = NULL;
 177 
 178       if (overrides[current_override].address)
 179          base = overrides[current_override].address;
 180       else
 181          for (; !base && (current_base < NO_BASES); ++current_base) {
 182 #if (DTCDEBUG & DTCDEBUG_INIT)
 183          printk("scsi : probing address %08x\n", (unsigned int) bases[current_base].address);
 184 #endif
 185          for (sig = 0; sig < NO_SIGNATURES; ++sig)
 186             if (!bases[current_base].noauto && !memcmp
 187               (bases[current_base].address + signatures[sig].offset,
 188               signatures[sig].string, strlen(signatures[sig].string))) {
 189             base = bases[current_base].address;
 190 #if (DTCDEBUG & DTCDEBUG_INIT)
 191             printk("scsi-dtc : detected board.\n");
 192 #endif
 193             break;
 194          }
 195       }
 196 
 197 #if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
 198       printk("scsi-dtc : base = %08x\n", (unsigned int) base);
 199 #endif
 200 
 201       if (!base)
 202          break;
 203 
 204       instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
 205       instance->base = base;
 206 
 207       NCR5380_init(instance, 0);
 208 
 209       NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR); /* Enable int's */
 210       if (overrides[current_override].irq != IRQ_AUTO)
 211          instance->irq = overrides[current_override].irq;
 212       else
 213          instance->irq = NCR5380_probe_irq(instance, DTC_IRQS);
 214 
 215 #ifndef DONT_USE_INTR
 216 /* With interrupts enabled, it will sometimes hang when doing heavy
 217  * reads. So better not enable them until I finger it out. */
 218       if (instance->irq != IRQ_NONE)
 219          if (request_irq(instance->irq, dtc_intr, SA_INTERRUPT, "dtc")) {
 220          printk("scsi%d : IRQ%d not free, interrupts disabled\n",
 221               instance->host_no, instance->irq);
 222          instance->irq = IRQ_NONE;
 223       }
 224 
 225       if (instance->irq == IRQ_NONE) {
 226          printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
 227          printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
 228       }
 229 #else
 230       if (instance->irq != IRQ_NONE)
 231          printk("scsi%d : interrupts not used. Might as well not jumper it.\n",
 232                 instance->host_no);
 233       instance->irq = IRQ_NONE;
 234 #endif
 235 #if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
 236       printk("scsi%d : irq = %d\n", instance->host_no, instance->irq);
 237 #endif
 238 
 239       printk("scsi%d : at 0x%05X", instance->host_no, (int)instance->base);
 240       if (instance->irq == IRQ_NONE)
 241          printk (" interrupts disabled");
 242       else
 243          printk (" irq %d", instance->irq);
 244       printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d",
 245            CAN_QUEUE, CMD_PER_LUN, DTC_PUBLIC_RELEASE);
 246       NCR5380_print_options(instance);
 247       printk("\n");
 248 
 249       ++current_override;
 250       ++count;
 251    }
 252    return count;
 253 }
 254 
 255 /*
 256  * Function : int dtc_biosparam(Disk * disk, kdev_t dev, int *ip)
 257  *
 258  * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for 
 259  *      the specified device / size.
 260  * 
 261  * Inputs : size = size of device in sectors (512 bytes), dev = block device
 262  *      major / minor, ip[] = {heads, sectors, cylinders}  
 263  *
 264  * Returns : always 0 (success), initializes ip
 265  *      
 266 */
 267 
 268 /* 
 269  * XXX Most SCSI boards use this mapping, I could be incorrect.  Some one
 270  * using hard disks on a trantor should verify that this mapping corresponds
 271  * to that used by the BIOS / ASPI driver by running the linux fdisk program
 272  * and matching the H_C_S coordinates to what DOS uses.
 273 */
 274 
 275 int dtc_biosparam(Disk * disk, kdev_t dev, int * ip)
     /* [previous][next][first][last][top][bottom][index][help] */
 276 {
 277    int size = disk->capacity;
 278 
 279    ip[0] = 64;
 280    ip[1] = 32;
 281    ip[2] = size >> 11;
 282    return 0;
 283 }
 284 
 285 /****************************************************************
 286  * Function : int NCR5380_pread (struct Scsi_Host *instance, 
 287  *      unsigned char *dst, int len)
 288  *
 289  * Purpose : Fast 5380 pseudo-dma read function, reads len bytes to 
 290  *      dst
 291  * 
 292  * Inputs : dst = destination, len = length in bytes
 293  *
 294  * Returns : 0 on success, non zero on a failure such as a watchdog 
 295  *      timeout.
 296 */
 297 
 298 static int dtc_maxi = 0;
 299 static int dtc_wmaxi = 0;
 300 
 301 static inline int NCR5380_pread (struct Scsi_Host *instance,
     /* [previous][next][first][last][top][bottom][index][help] */
 302      unsigned char *dst, int len)
 303      {
 304    unsigned char *d = dst;
 305    int i;       /* For counting time spent in the poll-loop */
 306    NCR5380_local_declare();
 307    NCR5380_setup(instance);
 308 
 309    i = 0;
 310    NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 311    NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
 312    if (instance->irq == IRQ_NONE)
 313       NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ);
 314    else
 315       NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE);
 316    NCR5380_write(DTC_BLK_CNT, len >> 7);        /* Block count */
 317    rtrc(1);
 318    while (len > 0) {
 319       rtrc(2);
 320       while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
 321          ++i;
 322       rtrc(3);
 323       memcpy(d, (char *)(base + DTC_DATA_BUF), 128);
 324       d += 128;
 325       len -= 128;
 326       rtrc(7);  /*** with int's on, it sometimes hangs after here.
 327                  * Looks like something makes HBNR go away. */
 328    }
 329    rtrc(4);
 330    while ( !(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS))
 331       ++i;
 332    NCR5380_write(MODE_REG, 0); /* Clear the operating mode */
 333    rtrc(0);
 334    NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 335    if (i > dtc_maxi)
 336       dtc_maxi = i;
 337    return(0);
 338 }
 339 
 340 /****************************************************************
 341  * Function : int NCR5380_pwrite (struct Scsi_Host *instance, 
 342  *      unsigned char *src, int len)
 343  *
 344  * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from
 345  *      src
 346  * 
 347  * Inputs : src = source, len = length in bytes
 348  *
 349  * Returns : 0 on success, non zero on a failure such as a watchdog 
 350  *      timeout.
 351 */
 352 
 353 static inline int NCR5380_pwrite (struct Scsi_Host *instance,
     /* [previous][next][first][last][top][bottom][index][help] */
 354      unsigned char *src, int len) {
 355    int i;
 356    NCR5380_local_declare();
 357    NCR5380_setup(instance);
 358 
 359    NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 360    NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
 361    /* set direction (write) */
 362    if (instance->irq == IRQ_NONE)
 363       NCR5380_write(DTC_CONTROL_REG, 0);
 364    else
 365       NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR);
 366    NCR5380_write(DTC_BLK_CNT, len >> 7);        /* Block count */
 367    for (i = 0; len > 0; ++i) {
 368       rtrc(5);
 369       /* Poll until the host buffer can accept data. */
 370       while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
 371          ++i;
 372       rtrc(3);
 373       memcpy((char *)(base + DTC_DATA_BUF), src, 128);
 374       src += 128;
 375       len -= 128;
 376    }
 377    rtrc(4);
 378    while ( !(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS))
 379       ++i;
 380    rtrc(6);
 381    /* Wait until the last byte has been sent to the disk */
 382    while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT))
 383       ++i;
 384    rtrc(7);
 385    /* Check for parity error here. fixme. */
 386    NCR5380_write(MODE_REG, 0); /* Clear the operating mode */
 387    rtrc(0);
 388    if (i > dtc_wmaxi)
 389       dtc_wmaxi = i;
 390    return (0);
 391 }
 392 
 393 #include "NCR5380.c"
 394 
 395 #ifdef MODULE
 396 /* Eventually this will go into an include file, but this will be later */
 397 Scsi_Host_Template driver_template = DTC3x80;
 398 
 399 #include "scsi_module.c"
 400 #endif

/* [previous][next][first][last][top][bottom][index][help] */