home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / drivers / scsi / t128.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-01  |  10.2 KB  |  392 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 tupples.  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.  
  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 paramters 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. static struct sigaction t128_sigaction =  { t128_intr, 0, SA_INTERRUPT , NULL };
  182.  
  183. /* 
  184.  * Function : int t128_detect(int hostno)
  185.  *
  186.  * Purpose : detects and initializes T128,T128F, or T228 controllers
  187.  *    that were autoprobed, overriden on the LILO command line, 
  188.  *    or specified at compile time.
  189.  *
  190.  * Inputs : hostno - id of this SCSI adapter.
  191.  * 
  192.  * Returns : 1 if a host adapter was found, 0 if not.
  193.  *
  194.  */
  195.  
  196. int t128_detect(int hostno) {
  197.     static int current_override = 0, current_base = 0;
  198.     struct Scsi_Host *instance;
  199.     unsigned char *base;
  200.     int sig, count;
  201.  
  202.     for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
  203.     base = NULL;
  204.  
  205.     if (overrides[current_override].address)
  206.         base = overrides[current_override].address;
  207.     else 
  208.         for (; !base && (current_base < NO_BASES); ++current_base) {
  209. #if (TDEBUG & TDEBUG_INIT)
  210.     printk("scsi%d : probing address %08x\n", hostno, (unsigned int) bases[current_base].address);
  211. #endif
  212.         for (sig = 0; sig < NO_SIGNATURES; ++sig) 
  213.             if (!bases[current_base].noauto && !memcmp 
  214.             (bases[current_base].address + signatures[sig].offset, 
  215.             signatures[sig].string, strlen(signatures[sig].string))) {
  216.             base = bases[current_base].address;
  217. #if (TDEBUG & TDEBUG_INIT)
  218.             printk("scsi%d : detected board.\n", hostno);
  219. #endif
  220.             break;
  221.             }
  222.         }
  223.  
  224. #if defined(TDEBUG) && (TDEBUG & TDEBUG_INIT)
  225.     printk("scsi%d : base = %08x\n", hostno, (unsigned int) base);
  226. #endif
  227.  
  228.     if (!base)
  229.         break;
  230.  
  231.     instance = scsi_register (hostno, sizeof(struct NCR5380_hostdata));
  232.     instance->base = base;
  233.  
  234.     NCR5380_init(instance);
  235.  
  236.     if (overrides[current_override].irq != IRQ_AUTO)
  237.         instance->irq = overrides[current_override].irq;
  238.     else 
  239.         instance->irq = NCR5380_probe_irq(instance, T128_IRQS);
  240.  
  241.     if (instance->irq != IRQ_NONE) 
  242.         if (irqaction (instance->irq, &t128_sigaction)) {
  243.         printk("scsi%d : IRQ%d not free, interrupts disabled\n", 
  244.             hostno, instance->irq);
  245.         instance->irq = IRQ_NONE;
  246.         } 
  247.  
  248.     if (instance->irq == IRQ_NONE) {
  249.         printk("scsi%d : interrupts not enabled. for better interactive performance,\n", hostno);
  250.         printk("scsi%d : please jumper the board for a free IRQ.\n", hostno);
  251.     }
  252.  
  253. #if defined(TDEBUG) && (TDEBUG & TDEBUG_INIT)
  254.     printk("scsi%d : irq = %d\n", hostno, instance->irq);
  255. #endif
  256.  
  257.     printk("scsi%d : at 0x%08x", instance->host_no, (int) 
  258.         instance->base);
  259.     if (instance->irq == IRQ_NONE)
  260.         printk (" interrupts disabled");
  261.     else 
  262.         printk (" irq %d", instance->irq);
  263.     printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d",
  264.         CAN_QUEUE, CMD_PER_LUN, T128_PUBLIC_RELEASE);
  265.     NCR5380_print_options(instance);
  266.     printk("\n");
  267.  
  268.     ++current_override;
  269.     ++count;
  270.     ++hostno;
  271.     }
  272.     return count;
  273. }
  274.  
  275. /*
  276.  * Function : int t128_biosparam(int size, int dev, int *ip)
  277.  *
  278.  * Purpose : Generates a BIOS / DOS compatable H-C-S mapping for 
  279.  *    the specified device / size.
  280.  * 
  281.  * Inputs : size = size of device in sectors (512 bytes), dev = block device
  282.  *    major / minor, ip[] = {heads, sectors, cylinders}  
  283.  *
  284.  * Returns : allways 0 (success), initializes ip
  285.  *    
  286.  */
  287.  
  288. /* 
  289.  * XXX Most SCSI boards use this mapping, I could be incorrect.  Some one
  290.  * using hard disks on a trantor should verify that this mapping corresponds
  291.  * to that used by the BIOS / ASPI driver by running the linux fdisk program
  292.  * and matching the H_C_S coordinates to what DOS uses.
  293.  */
  294.  
  295. int t128_biosparam(int size, int dev, int * ip)
  296. {
  297.   ip[0] = 64;
  298.   ip[1] = 32;
  299.   ip[2] = size >> 11;
  300.   return 0;
  301. }
  302.  
  303. /*
  304.  * Function : int NCR5380_pread (struct Scsi_Host *instance, 
  305.  *    unsigned char *dst, int len)
  306.  *
  307.  * Purpose : Fast 5380 pseudo-dma read function, transfers len bytes to 
  308.  *    dst
  309.  * 
  310.  * Inputs : dst = destination, len = length in bytes
  311.  *
  312.  * Returns : 0 on success, non zero on a failure such as a watchdog 
  313.  *     timeout.
  314.  */
  315.  
  316. static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst,
  317.     int len) {
  318.     register unsigned char *reg = (unsigned char *) (instance->base + 
  319.     T_DATA_REG_OFFSET), *d = dst;
  320.     register i = len;
  321.  
  322.     while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY);
  323.  
  324.     for (; i; --i) 
  325.     *d++ = *reg;
  326.  
  327.     if (*(instance->base + T_STATUS_REG_OFFSET) & T_ST_TIM) {
  328.     unsigned char tmp;
  329.     volatile unsigned char *foo;
  330.     foo = instance->base + T_CONTROL_REG_OFFSET;
  331.     tmp = *foo;
  332.     *foo = tmp | T_CR_CT;
  333.     *foo = tmp;
  334.     printk("scsi%d : watchdog timer fired in NCR5480_pread()\n",
  335.         instance->host_no);
  336.     return -1;
  337.     } else
  338.     return 0;
  339. }
  340.  
  341. /*
  342.  * Function : int NCR5380_pwrite (struct Scsi_Host *instance, 
  343.  *    unsigned char *src, int len)
  344.  *
  345.  * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from
  346.  *    src
  347.  * 
  348.  * Inputs : src = source, len = length in bytes
  349.  *
  350.  * Returns : 0 on success, non zero on a failure such as a watchdog 
  351.  *     timeout.
  352.  */
  353.  
  354. static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src,
  355.     int len) {
  356.     register unsigned char *reg = (unsigned char *) (instance->base + 
  357.     T_DATA_REG_OFFSET), *s = src;
  358.     register i = len;
  359.  
  360.     while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY);
  361.     for (; i; --i)
  362.     *reg = *s++;
  363.  
  364.     if (*(instance->base + T_STATUS_REG_OFFSET) & T_ST_TIM) {
  365.     unsigned char tmp;
  366.     volatile unsigned char *foo;
  367.     foo = instance->base + T_CONTROL_REG_OFFSET;
  368.     tmp = *foo;
  369.     *foo = tmp | T_CR_CT;
  370.     *foo = tmp;
  371.     printk("scsi%d : watchdog timer fired in NCR5480_pwrite()\n",
  372.         instance->host_no);
  373.     return -1;
  374.     } else 
  375.     return 0;
  376. }
  377.  
  378. /*
  379.  * Function : const char *t128_info(void)
  380.  *
  381.  * Purpose : provide furthur information about this driver.
  382.  *
  383.  * Returns : an empty string.
  384.  */
  385.  
  386. const char *t128_info (void) {
  387.     static const char string[]="";
  388.     return string;
  389. }
  390.  
  391. #include "NCR5380.c"
  392.