Annotation of Gnu-Mach/linux/src/drivers/scsi/dtc.c, revision 1.1.1.1

1.1       root        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  [email protected]
                     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:  *     [email protected]
                     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:    __u32 address;
                     98:    int irq;
                     99: } overrides
                    100: #ifdef OVERRIDE
                    101: [] = OVERRIDE;
                    102: #else
                    103: [4] = {{0, IRQ_AUTO}, {0, IRQ_AUTO}, {0, IRQ_AUTO},
                    104:        {0, IRQ_AUTO}};
                    105: #endif
                    106: 
                    107: #define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
                    108: 
                    109: static struct base {
                    110:    __u32 address;
                    111:    int noauto;
                    112: } bases[] = {{0xcc000, 0}, {0xc8000, 0},
                    113: {0xdc000, 0}, {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 = ints[1];
                    142:       overrides[commandline_current].irq = ints[2];
                    143:       for (i = 0; i < NO_BASES; ++i)
                    144:         if (bases[i].address == 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) {
                    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 = (unsigned char *)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:              ((unsigned char *)(bases[current_base].address + signatures[sig].offset),
                    188:              signatures[sig].string, strlen(signatures[sig].string))) {
                    189:            base = (unsigned char *)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)
                    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,
                    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,
                    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

unix.superglobalmegacorp.com

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