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