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