home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / drivers / scsi / t128.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-29  |  10.2 KB  |  389 lines

  1. #define AUTOSENSE
  2. #define PSEUDO_DMA
  3.  
  4. /*
  5.  * Trantor T128/T128F/T228 driver
  6.  *    Note : architecturally, the T100 and T130 are different and won't 
  7.  *     work
  8.  *
  9.  * Copyright 1993, Drew Eckhardt
  10.  *    Visionary Computing
  11.  *    (Unix and Linux consulting and custom programming)
  12.  *    drew@colorado.edu
  13.  *      +1 (303) 440-4894
  14.  *
  15.  * DISTRIBUTION RELEASE 3.
  16.  *
  17.  * For more information, please consult 
  18.  *
  19.  * Trantor Systems, Ltd.
  20.  * T128/T128F/T228 SCSI Host Adapter
  21.  * Hardware Specifications
  22.  * 
  23.  * Trantor Systems, Ltd. 
  24.  * 5415 Randall Place
  25.  * Fremont, CA 94538
  26.  * 1+ (415) 770-1400, FAX 1+ (415) 770-9910
  27.  * 
  28.  * and 
  29.  *
  30.  * NCR 5380 Family
  31.  * SCSI Protocol Controller
  32.  * Databook
  33.  *
  34.  * NCR Microelectronics
  35.  * 1635 Aeroplaza Drive
  36.  * Colorado Springs, CO 80916
  37.  * 1+ (719) 578-3400
  38.  * 1+ (800) 334-5454
  39.  */
  40.  
  41. /*
  42.  * Options : 
  43.  * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
  44.  *      for commands that return with a CHECK CONDITION status. 
  45.  *
  46.  * PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance
  47.  * increase compared to polled I/O.
  48.  *
  49.  * PARITY - enable parity checking.  Not supported.
  50.  * 
  51.  * SCSI2 - enable support for SCSI-II tagged queueing.  Untested.
  52.  *
  53.  *
  54.  * UNSAFE - leave interrupts enabled during pseudo-DMA transfers.  You
  55.  *          only really want to use this if you're having a problem with
  56.  *          dropped characters during high speed communications, and even
  57.  *          then, you're going to be better off twiddling with transfersize.
  58.  *
  59.  * USLEEP - enable support for devices that don't disconnect.  Untested.
  60.  *
  61.  * The card is detected and initialized in one of several ways : 
  62.  * 1.  Autoprobe (default) - since the board is memory mapped, 
  63.  *     a BIOS signature is scanned for to locate the registers.
  64.  *     An interrupt is triggered to autoprobe for the interrupt
  65.  *     line.
  66.  *
  67.  * 2.  With command line overrides - t128=address,irq may be 
  68.  *     used on the LILO command line to override the defaults.
  69.  *
  70.  * 3.  With the T128_OVERRIDE compile time define.  This is 
  71.  *     specified as an array of address, irq tuples.  Ie, for
  72.  *     one board at the default 0xcc000 address, IRQ5, I could say 
  73.  *     -DT128_OVERRIDE={{0xcc000, 5}}
  74.  *    
  75.  *     Note that if the override methods are used, place holders must
  76.  *     be specified for other boards in the system.
  77.  * 
  78.  * T128/T128F jumper/dipswitch settings (note : on my sample, the switches 
  79.  * were epoxy'd shut, meaning I couldn't change the 0xcc000 base address) :
  80.  *
  81.  * T128    Sw7 Sw8 Sw6 = 0ws Sw5 = boot 
  82.  * T128F   Sw6 Sw7 Sw5 = 0ws Sw4 = boot Sw8 = floppy disable
  83.  * cc000   off off      
  84.  * c8000   off on
  85.  * dc000   on  off
  86.  * d8000   on  on
  87.  *
  88.  * 
  89.  * Interrupts 
  90.  * There is a 12 pin jumper block, jp1, numbered as follows : 
  91.  *   T128 (JP1)       T128F (J5)
  92.  * 2 4 6 8 10 12    11 9  7 5 3 1
  93.  * 1 3 5 7 9  11    12 10 8 6 4 2
  94.  *
  95.  * 3   2-4
  96.  * 5   1-3
  97.  * 7   3-5
  98.  * T128F only 
  99.  * 10 8-10
  100.  * 12 7-9
  101.  * 14 10-12
  102.  * 15 9-11
  103.  */
  104.  
  105. /*
  106.  * $Log: t128.c,v $
  107.  */
  108.  
  109. #include <asm/system.h>
  110. #include <linux/signal.h>
  111. #include <linux/sched.h>
  112. #include "../block/blk.h"
  113. #include "scsi.h"
  114. #include "hosts.h"
  115. #include "t128.h"
  116. #define AUTOPROBE_IRQ
  117. #include "NCR5380.h"
  118. #include "constants.h"
  119. #include "sd.h"
  120.  
  121.  
  122.  
  123. static struct override {
  124.     unsigned char *address;
  125.     int irq;
  126. } overrides 
  127. #ifdef T128_OVERRIDE
  128.     [] = T128_OVERRIDE;
  129. #else
  130.     [4] = {{NULL,IRQ_AUTO}, {NULL,IRQ_AUTO}, {NULL,IRQ_AUTO},
  131.     {NULL,IRQ_AUTO}};
  132. #endif
  133.  
  134. #define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
  135.  
  136. static struct base {
  137.     unsigned char *address;
  138.     int noauto;
  139. } bases[] = {{(unsigned char *) 0xcc000, 0}, {(unsigned char *) 0xc8000, 0},
  140.     {(unsigned char *) 0xdc000, 0}, {(unsigned char *) 0xd8000, 0}};
  141.  
  142. #define NO_BASES (sizeof (bases) / sizeof (struct base))
  143.  
  144. static const struct signature {
  145.     const char *string;
  146.     int offset;
  147. } signatures[] = {
  148. {"TSROM: SCSI BIOS, Version 1.12", 0x36},
  149. };
  150.  
  151. #define NO_SIGNATURES (sizeof (signatures) /  sizeof (struct signature))
  152.  
  153. /*
  154.  * Function : t128_setup(char *str, int *ints)
  155.  *
  156.  * Purpose : LILO command line initialization of the overrides array,
  157.  * 
  158.  * Inputs : str - unused, ints - array of integer parameters with ints[0]
  159.  *    equal to the number of ints.
  160.  *
  161.  */
  162.  
  163. void t128_setup(char *str, int *ints) {
  164.     static int commandline_current = 0;
  165.     int i;
  166.     if (ints[0] != 2) 
  167.     printk("t128_setup : usage t128=address,irq\n");
  168.     else 
  169.     if (commandline_current < NO_OVERRIDES) {
  170.         overrides[commandline_current].address = (unsigned char *) ints[1];
  171.         overrides[commandline_current].irq = ints[2];
  172.         for (i = 0; i < NO_BASES; ++i)
  173.         if (bases[i].address == (unsigned char *) ints[1]) {
  174.             bases[i].noauto = 1;
  175.             break;
  176.         }
  177.         ++commandline_current;
  178.     }
  179. }
  180.  
  181. /* 
  182.  * Function : int t128_detect(Scsi_Host_Template * tpnt)
  183.  *
  184.  * Purpose : detects and initializes T128,T128F, or T228 controllers
  185.  *    that were autoprobed, overridden on the LILO command line, 
  186.  *    or specified at compile time.
  187.  *
  188.  * Inputs : tpnt - template for this SCSI adapter.
  189.  * 
  190.  * Returns : 1 if a host adapter was found, 0 if not.
  191.  *
  192.  */
  193.  
  194. int t128_detect(Scsi_Host_Template * tpnt) {
  195.     static int current_override = 0, current_base = 0;
  196.     struct Scsi_Host *instance;
  197.     unsigned char *base;
  198.     int sig, count;
  199.  
  200.     for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
  201.     base = NULL;
  202.  
  203.     if (overrides[current_override].address)
  204.         base = overrides[current_override].address;
  205.     else 
  206.         for (; !base && (current_base < NO_BASES); ++current_base) {
  207. #if (TDEBUG & TDEBUG_INIT)
  208.     printk("scsi : probing address %08x\n", (unsigned int) bases[current_base].address);
  209. #endif
  210.         for (sig = 0; sig < NO_SIGNATURES; ++sig) 
  211.             if (!bases[current_base].noauto && !memcmp 
  212.             (bases[current_base].address + signatures[sig].offset, 
  213.             signatures[sig].string, strlen(signatures[sig].string))) {
  214.             base = bases[current_base].address;
  215. #if (TDEBUG & TDEBUG_INIT)
  216.             printk("scsi-t128 : detected board.\n");
  217. #endif
  218.             break;
  219.             }
  220.         }
  221.  
  222. #if defined(TDEBUG) && (TDEBUG & TDEBUG_INIT)
  223.     printk("scsi-t128 : base = %08x\n", (unsigned int) base);
  224. #endif
  225.  
  226.     if (!base)
  227.         break;
  228.  
  229.     instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
  230.     instance->base = base;
  231.  
  232.     NCR5380_init(instance, 0);
  233.  
  234.     if (overrides[current_override].irq != IRQ_AUTO)
  235.         instance->irq = overrides[current_override].irq;
  236.     else 
  237.         instance->irq = NCR5380_probe_irq(instance, T128_IRQS);
  238.  
  239.     if (instance->irq != IRQ_NONE) 
  240.         if (request_irq(instance->irq, t128_intr, SA_INTERRUPT, "t128")) {
  241.         printk("scsi%d : IRQ%d not free, interrupts disabled\n", 
  242.             instance->host_no, instance->irq);
  243.         instance->irq = IRQ_NONE;
  244.         } 
  245.  
  246.     if (instance->irq == IRQ_NONE) {
  247.         printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
  248.         printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
  249.     }
  250.  
  251. #if defined(TDEBUG) && (TDEBUG & TDEBUG_INIT)
  252.     printk("scsi%d : irq = %d\n", instance->host_no, instance->irq);
  253. #endif
  254.  
  255.     printk("scsi%d : at 0x%08x", instance->host_no, (int) 
  256.         instance->base);
  257.     if (instance->irq == IRQ_NONE)
  258.         printk (" interrupts disabled");
  259.     else 
  260.         printk (" irq %d", instance->irq);
  261.     printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d",
  262.         CAN_QUEUE, CMD_PER_LUN, T128_PUBLIC_RELEASE);
  263.     NCR5380_print_options(instance);
  264.     printk("\n");
  265.  
  266.     ++current_override;
  267.     ++count;
  268.     }
  269.     return count;
  270. }
  271.  
  272. /*
  273.  * Function : int t128_biosparam(Disk * disk, int dev, int *ip)
  274.  *
  275.  * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for 
  276.  *    the specified device / size.
  277.  * 
  278.  * Inputs : size = size of device in sectors (512 bytes), dev = block device
  279.  *    major / minor, ip[] = {heads, sectors, cylinders}  
  280.  *
  281.  * Returns : always 0 (success), initializes ip
  282.  *    
  283.  */
  284.  
  285. /* 
  286.  * XXX Most SCSI boards use this mapping, I could be incorrect.  Some one
  287.  * using hard disks on a trantor should verify that this mapping corresponds
  288.  * to that used by the BIOS / ASPI driver by running the linux fdisk program
  289.  * and matching the H_C_S coordinates to what DOS uses.
  290.  */
  291.  
  292. int t128_biosparam(Disk * disk, int dev, int * ip)
  293. {
  294.   int size = disk->capacity;
  295.   ip[0] = 64;
  296.   ip[1] = 32;
  297.   ip[2] = size >> 11;
  298.   return 0;
  299. }
  300.  
  301. /*
  302.  * Function : int NCR5380_pread (struct Scsi_Host *instance, 
  303.  *    unsigned char *dst, int len)
  304.  *
  305.  * Purpose : Fast 5380 pseudo-dma read function, transfers len bytes to 
  306.  *    dst
  307.  * 
  308.  * Inputs : dst = destination, len = length in bytes
  309.  *
  310.  * Returns : 0 on success, non zero on a failure such as a watchdog 
  311.  *     timeout.
  312.  */
  313.  
  314. static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst,
  315.     int len) {
  316.     register unsigned char *reg = (unsigned char *) (instance->base + 
  317.     T_DATA_REG_OFFSET), *d = dst;
  318.     register i = len;
  319.  
  320.  
  321. #if 0
  322.     for (; i; --i) {
  323.     while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY);
  324. #else
  325.     while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY);
  326.     for (; i; --i) {
  327. #endif
  328.     *d++ = *reg;
  329.     }
  330.  
  331.     if (*(instance->base + T_STATUS_REG_OFFSET) & T_ST_TIM) {
  332.     unsigned char tmp;
  333.     volatile unsigned char *foo;
  334.     foo = instance->base + T_CONTROL_REG_OFFSET;
  335.     tmp = *foo;
  336.     *foo = tmp | T_CR_CT;
  337.     *foo = tmp;
  338.     printk("scsi%d : watchdog timer fired in NCR5380_pread()\n",
  339.         instance->host_no);
  340.     return -1;
  341.     } else
  342.     return 0;
  343. }
  344.  
  345. /*
  346.  * Function : int NCR5380_pwrite (struct Scsi_Host *instance, 
  347.  *    unsigned char *src, int len)
  348.  *
  349.  * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from
  350.  *    src
  351.  * 
  352.  * Inputs : src = source, len = length in bytes
  353.  *
  354.  * Returns : 0 on success, non zero on a failure such as a watchdog 
  355.  *     timeout.
  356.  */
  357.  
  358. static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src,
  359.     int len) {
  360.     register unsigned char *reg = (unsigned char *) (instance->base + 
  361.     T_DATA_REG_OFFSET), *s = src;
  362.     register i = len;
  363.  
  364. #if 0
  365.     for (; i; --i) {
  366.     while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY);
  367. #else
  368.     while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY);
  369.     for (; i; --i) {
  370. #endif
  371.     *reg = *s++;
  372.     }
  373.  
  374.     if (*(instance->base + T_STATUS_REG_OFFSET) & T_ST_TIM) {
  375.     unsigned char tmp;
  376.     volatile unsigned char *foo;
  377.     foo = instance->base + T_CONTROL_REG_OFFSET;
  378.     tmp = *foo;
  379.     *foo = tmp | T_CR_CT;
  380.     *foo = tmp;
  381.     printk("scsi%d : watchdog timer fired in NCR5380_pwrite()\n",
  382.         instance->host_no);
  383.     return -1;
  384.     } else 
  385.     return 0;
  386. }
  387.  
  388. #include "NCR5380.c"
  389.