|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.