Annotation of Gnu-Mach/i386/i386at/gpl/linux/scsi/t128.c, revision 1.1.1.1

1.1       root        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:  *     [email protected]
                     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:  * Revision 1.1.1.1  1997/02/25 21:27:53  thomas
                    108:  * Initial source
                    109:  *
                    110:  * Revision 1.1.1.1  1996/10/30 01:40:07  thomas
                    111:  * Imported from UK22
                    112:  *
                    113:  * Revision 1.1  1996/03/25  20:25:52  goel
                    114:  * Linux driver merge.
                    115:  *
                    116:  */
                    117: 
                    118: #include <asm/system.h>
                    119: #include <linux/signal.h>
                    120: #include <linux/sched.h>
                    121: #include <asm/io.h>
                    122: #include <linux/blk.h>
                    123: #include "scsi.h"
                    124: #include "hosts.h"
                    125: #include "t128.h"
                    126: #define AUTOPROBE_IRQ
                    127: #include "NCR5380.h"
                    128: #include "constants.h"
                    129: #include "sd.h"
                    130: #include<linux/stat.h>
                    131: 
                    132: struct proc_dir_entry proc_scsi_t128 = {
                    133:     PROC_SCSI_T128, 4, "t128",
                    134:     S_IFDIR | S_IRUGO | S_IXUGO, 2
                    135: };
                    136: 
                    137: 
                    138: static struct override {
                    139:     unsigned char *address;
                    140:     int irq;
                    141: } overrides 
                    142: #ifdef T128_OVERRIDE
                    143:     [] = T128_OVERRIDE;
                    144: #else
                    145:     [4] = {{NULL,IRQ_AUTO}, {NULL,IRQ_AUTO}, {NULL,IRQ_AUTO},
                    146:        {NULL,IRQ_AUTO}};
                    147: #endif
                    148: 
                    149: #define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
                    150: 
                    151: static struct base {
                    152:     unsigned char *address;
                    153:     int noauto;
                    154: } bases[] = {{(unsigned char *) 0xcc000, 0}, {(unsigned char *) 0xc8000, 0},
                    155:     {(unsigned char *) 0xdc000, 0}, {(unsigned char *) 0xd8000, 0}};
                    156: 
                    157: #define NO_BASES (sizeof (bases) / sizeof (struct base))
                    158: 
                    159: static const struct signature {
                    160:     const char *string;
                    161:     int offset;
                    162: } signatures[] = {
                    163: {"TSROM: SCSI BIOS, Version 1.12", 0x36},
                    164: };
                    165: 
                    166: #define NO_SIGNATURES (sizeof (signatures) /  sizeof (struct signature))
                    167: 
                    168: /*
                    169:  * Function : t128_setup(char *str, int *ints)
                    170:  *
                    171:  * Purpose : LILO command line initialization of the overrides array,
                    172:  * 
                    173:  * Inputs : str - unused, ints - array of integer parameters with ints[0]
                    174:  *     equal to the number of ints.
                    175:  *
                    176:  */
                    177: 
                    178: void t128_setup(char *str, int *ints) {
                    179:     static int commandline_current = 0;
                    180:     int i;
                    181:     if (ints[0] != 2) 
                    182:        printk("t128_setup : usage t128=address,irq\n");
                    183:     else 
                    184:        if (commandline_current < NO_OVERRIDES) {
                    185:            overrides[commandline_current].address = (unsigned char *) ints[1];
                    186:            overrides[commandline_current].irq = ints[2];
                    187:            for (i = 0; i < NO_BASES; ++i)
                    188:                if (bases[i].address == (unsigned char *) ints[1]) {
                    189:                    bases[i].noauto = 1;
                    190:                    break;
                    191:                }
                    192:            ++commandline_current;
                    193:        }
                    194: }
                    195: 
                    196: /* 
                    197:  * Function : int t128_detect(Scsi_Host_Template * tpnt)
                    198:  *
                    199:  * Purpose : detects and initializes T128,T128F, or T228 controllers
                    200:  *     that were autoprobed, overridden on the LILO command line, 
                    201:  *     or specified at compile time.
                    202:  *
                    203:  * Inputs : tpnt - template for this SCSI adapter.
                    204:  * 
                    205:  * Returns : 1 if a host adapter was found, 0 if not.
                    206:  *
                    207:  */
                    208: 
                    209: int t128_detect(Scsi_Host_Template * tpnt) {
                    210:     static int current_override = 0, current_base = 0;
                    211:     struct Scsi_Host *instance;
                    212:     unsigned char *base;
                    213:     int sig, count;
                    214: 
                    215:     tpnt->proc_dir = &proc_scsi_t128;
                    216: 
                    217:     for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
                    218:        base = NULL;
                    219: 
                    220:        if (overrides[current_override].address)
                    221:            base = overrides[current_override].address;
                    222:        else 
                    223:            for (; !base && (current_base < NO_BASES); ++current_base) {
                    224: #if (TDEBUG & TDEBUG_INIT)
                    225:     printk("scsi : probing address %08x\n", (unsigned int) bases[current_base].address);
                    226: #endif
                    227:                for (sig = 0; sig < NO_SIGNATURES; ++sig) 
                    228:                    if (!bases[current_base].noauto && !memcmp 
                    229:                        (bases[current_base].address + signatures[sig].offset, 
                    230:                        signatures[sig].string, strlen(signatures[sig].string))) {
                    231:                        base = bases[current_base].address;
                    232: #if (TDEBUG & TDEBUG_INIT)
                    233:                        printk("scsi-t128 : detected board.\n");
                    234: #endif
                    235:                        break;
                    236:                    }
                    237:            }
                    238: 
                    239: #if defined(TDEBUG) && (TDEBUG & TDEBUG_INIT)
                    240:        printk("scsi-t128 : base = %08x\n", (unsigned int) base);
                    241: #endif
                    242: 
                    243:        if (!base)
                    244:            break;
                    245: 
                    246:        instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
                    247:        instance->base = base;
                    248: 
                    249:        NCR5380_init(instance, 0);
                    250: 
                    251:        if (overrides[current_override].irq != IRQ_AUTO)
                    252:            instance->irq = overrides[current_override].irq;
                    253:        else 
                    254:            instance->irq = NCR5380_probe_irq(instance, T128_IRQS);
                    255: 
                    256:        if (instance->irq != IRQ_NONE) 
                    257:            if (request_irq(instance->irq, t128_intr, SA_INTERRUPT, "t128")) {
                    258:                printk("scsi%d : IRQ%d not free, interrupts disabled\n", 
                    259:                    instance->host_no, instance->irq);
                    260:                instance->irq = IRQ_NONE;
                    261:            } 
                    262: 
                    263:        if (instance->irq == IRQ_NONE) {
                    264:            printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
                    265:            printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
                    266:        }
                    267: 
                    268: #if defined(TDEBUG) && (TDEBUG & TDEBUG_INIT)
                    269:        printk("scsi%d : irq = %d\n", instance->host_no, instance->irq);
                    270: #endif
                    271: 
                    272:        printk("scsi%d : at 0x%08x", instance->host_no, (int) 
                    273:            instance->base);
                    274:        if (instance->irq == IRQ_NONE)
                    275:            printk (" interrupts disabled");
                    276:        else 
                    277:            printk (" irq %d", instance->irq);
                    278:        printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d",
                    279:            CAN_QUEUE, CMD_PER_LUN, T128_PUBLIC_RELEASE);
                    280:        NCR5380_print_options(instance);
                    281:        printk("\n");
                    282: 
                    283:        ++current_override;
                    284:        ++count;
                    285:     }
                    286:     return count;
                    287: }
                    288: 
                    289: /*
                    290:  * Function : int t128_biosparam(Disk * disk, kdev_t dev, int *ip)
                    291:  *
                    292:  * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for 
                    293:  *     the specified device / size.
                    294:  * 
                    295:  * Inputs : size = size of device in sectors (512 bytes), dev = block device
                    296:  *     major / minor, ip[] = {heads, sectors, cylinders}  
                    297:  *
                    298:  * Returns : always 0 (success), initializes ip
                    299:  *     
                    300:  */
                    301: 
                    302: /* 
                    303:  * XXX Most SCSI boards use this mapping, I could be incorrect.  Some one
                    304:  * using hard disks on a trantor should verify that this mapping corresponds
                    305:  * to that used by the BIOS / ASPI driver by running the linux fdisk program
                    306:  * and matching the H_C_S coordinates to what DOS uses.
                    307:  */
                    308: 
                    309: int t128_biosparam(Disk * disk, kdev_t dev, int * ip)
                    310: {
                    311:   int size = disk->capacity;
                    312:   ip[0] = 64;
                    313:   ip[1] = 32;
                    314:   ip[2] = size >> 11;
                    315:   return 0;
                    316: }
                    317: 
                    318: /*
                    319:  * Function : int NCR5380_pread (struct Scsi_Host *instance, 
                    320:  *     unsigned char *dst, int len)
                    321:  *
                    322:  * Purpose : Fast 5380 pseudo-dma read function, transfers len bytes to 
                    323:  *     dst
                    324:  * 
                    325:  * Inputs : dst = destination, len = length in bytes
                    326:  *
                    327:  * Returns : 0 on success, non zero on a failure such as a watchdog 
                    328:  *     timeout.
                    329:  */
                    330: 
                    331: static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst,
                    332:     int len) {
                    333:     register unsigned char *reg = (unsigned char *) (instance->base + 
                    334:        T_DATA_REG_OFFSET), *d = dst;
                    335:     register i = len;
                    336: 
                    337: 
                    338: #if 0
                    339:     for (; i; --i) {
                    340:        while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY) barrier();
                    341: #else
                    342:     while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY) barrier();
                    343:     for (; i; --i) {
                    344: #endif
                    345:        *d++ = *reg;
                    346:     }
                    347: 
                    348:     if (*(instance->base + T_STATUS_REG_OFFSET) & T_ST_TIM) {
                    349:        unsigned char tmp;
                    350:        volatile unsigned char *foo;
                    351:        foo = instance->base + T_CONTROL_REG_OFFSET;
                    352:        tmp = *foo;
                    353:        *foo = tmp | T_CR_CT;
                    354:        *foo = tmp;
                    355:        printk("scsi%d : watchdog timer fired in NCR5380_pread()\n",
                    356:            instance->host_no);
                    357:        return -1;
                    358:     } else
                    359:        return 0;
                    360: }
                    361: 
                    362: /*
                    363:  * Function : int NCR5380_pwrite (struct Scsi_Host *instance, 
                    364:  *     unsigned char *src, int len)
                    365:  *
                    366:  * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from
                    367:  *     src
                    368:  * 
                    369:  * Inputs : src = source, len = length in bytes
                    370:  *
                    371:  * Returns : 0 on success, non zero on a failure such as a watchdog 
                    372:  *     timeout.
                    373:  */
                    374: 
                    375: static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src,
                    376:     int len) {
                    377:     register unsigned char *reg = (unsigned char *) (instance->base + 
                    378:        T_DATA_REG_OFFSET), *s = src;
                    379:     register i = len;
                    380: 
                    381: #if 0
                    382:     for (; i; --i) {
                    383:        while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY) barrier();
                    384: #else
                    385:     while (!(instance->base[T_STATUS_REG_OFFSET]) & T_ST_RDY) barrier();
                    386:     for (; i; --i) {
                    387: #endif
                    388:        *reg = *s++;
                    389:     }
                    390: 
                    391:     if (*(instance->base + T_STATUS_REG_OFFSET) & T_ST_TIM) {
                    392:        unsigned char tmp;
                    393:        volatile unsigned char *foo;
                    394:        foo = instance->base + T_CONTROL_REG_OFFSET;
                    395:        tmp = *foo;
                    396:        *foo = tmp | T_CR_CT;
                    397:        *foo = tmp;
                    398:        printk("scsi%d : watchdog timer fired in NCR5380_pwrite()\n",
                    399:            instance->host_no);
                    400:        return -1;
                    401:     } else 
                    402:        return 0;
                    403: }
                    404: 
                    405: #ifdef MACH
                    406: #include "NCR5380.src"
                    407: #else
                    408: #include "NCR5380.c"
                    409: #endif
                    410: 
                    411: #ifdef MODULE
                    412: /* Eventually this will go into an include file, but this will be later */
                    413: Scsi_Host_Template driver_template = TRANTOR_T128;
                    414: 
                    415: #include "scsi_module.c"
                    416: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.