|
|
1.1 ! root 1: /* ! 2: * Generic Generic NCR5380 driver ! 3: * ! 4: * Copyright 1993, Drew Eckhardt ! 5: * Visionary Computing ! 6: * (Unix and Linux consulting and custom programming) ! 7: * [email protected] ! 8: * +1 (303) 440-4894 ! 9: * ! 10: * NCR53C400 extensions (c) 1994,1995,1996, Kevin Lentin ! 11: * [email protected] ! 12: * ! 13: * ALPHA RELEASE 1. ! 14: * ! 15: * For more information, please consult ! 16: * ! 17: * NCR 5380 Family ! 18: * SCSI Protocol Controller ! 19: * Databook ! 20: * ! 21: * NCR Microelectronics ! 22: * 1635 Aeroplaza Drive ! 23: * Colorado Springs, CO 80916 ! 24: * 1+ (719) 578-3400 ! 25: * 1+ (800) 334-5454 ! 26: */ ! 27: ! 28: /* ! 29: * TODO : flesh out DMA support, find some one actually using this (I have ! 30: * a memory mapped Trantor board that works fine) ! 31: */ ! 32: ! 33: /* ! 34: * Options : ! 35: * ! 36: * PARITY - enable parity checking. Not supported. ! 37: * ! 38: * SCSI2 - enable support for SCSI-II tagged queueing. Untested. ! 39: * ! 40: * USLEEP - enable support for devices that don't disconnect. Untested. ! 41: * ! 42: * The card is detected and initialized in one of several ways : ! 43: * 1. With command line overrides - NCR5380=port,irq may be ! 44: * used on the LILO command line to override the defaults. ! 45: * ! 46: * 2. With the GENERIC_NCR5380_OVERRIDE compile time define. This is ! 47: * specified as an array of address, irq, dma, board tuples. Ie, for ! 48: * one board at 0x350, IRQ5, no dma, I could say ! 49: * -DGENERIC_NCR5380_OVERRIDE={{0xcc000, 5, DMA_NONE, BOARD_NCR5380}} ! 50: * ! 51: * -1 should be specified for no or DMA interrupt, -2 to autoprobe for an ! 52: * IRQ line if overridden on the command line. ! 53: * ! 54: * 3. When included as a module, with arguments passed on the command line: ! 55: * ncr_irq=xx the interrupt ! 56: * ncr_addr=xx the port or base address (for port or memory ! 57: * mapped, resp.) ! 58: * ncr_dma=xx the DMA ! 59: * ncr_5380=1 to set up for a NCR5380 board ! 60: * ncr_53c400=1 to set up for a NCR53C400 board ! 61: * e.g. ! 62: * modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_5380=1 ! 63: * for a port mapped NCR5380 board or ! 64: * modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1 ! 65: * for a memory mapped NCR53C400 board with interrupts disabled. ! 66: * ! 67: * 255 should be specified for no or DMA interrupt, 254 to autoprobe for an ! 68: * IRQ line if overridden on the command line. ! 69: * ! 70: */ ! 71: ! 72: /* ! 73: * $Log: g_NCR5380.c,v $ ! 74: * Revision 1.1 1999/04/26 05:54:33 tb ! 75: * 1998-11-30 OKUJI Yoshinori <[email protected]> ! 76: * ! 77: * Clean up linux emulation code to make it architecture-independent ! 78: * as much as possible. ! 79: * ! 80: * * linux: Renamed from linuxdev. ! 81: * * Makefile.in (objfiles): Add linux.o instead of linuxdev.o. ! 82: * (MAKE): New variable. Used for the linux.o target. ! 83: * * configure.in: Add AC_CHECK_TOOL(MAKE, make). ! 84: * * i386/i386/spl.h: Include <i386/ipl.h>, for compatibility with ! 85: * OSF Mach 3.0. Suggested by Elgin Lee <[email protected]>. ! 86: * * linux/src: Renamed from linux/linux. ! 87: * * linux/dev: Renamed from linux/mach. ! 88: * * linux/Drivers.in (AC_INIT): Use dev/include/linux/autoconf.h, ! 89: * instead of mach/include/linux/autoconf.h. ! 90: * * Makefile.in (all): Target ../linux.o instead of ../linuxdev.o. ! 91: * * linux/dev/drivers/block/genhd.c: Include <machine/spl.h> instead ! 92: * of <i386/ipl.h>. ! 93: * * linux/dev/drivers/net/auto_irq.c: Remove unneeded header files, ! 94: * <i386/ipl.h> and <i386/pic.h>. ! 95: * * linux/dev/init/main.c: Many i386-dependent codes moved to ... ! 96: * * linux/dev/arch/i386/irq.c: ... here. ! 97: * * linux/dev/arch/i386/setup.c: New file. ! 98: * * linux/dev/arch/i386/linux_emul.h: Likewise. ! 99: * * linux/dev/arch/i386/glue/timer.c: Merged into sched.c. ! 100: * * linux/dev/arch/i386/glue/sched.c: Include <machine/spl.h> instead ! 101: * of <i386/ipl.h>, and moved to ... ! 102: * * linux/dev/kernel/sched.c: ... here. ! 103: * * linux/dev/arch/i386/glue/block.c: Include <machine/spl.h> and ! 104: * <linux_emul.h>, instead of i386-dependent header files, and ! 105: * moved to ... ! 106: * * linux/dev/glue/blocl.c: ... here. ! 107: * * linux/dev/arch/i386/glue/net.c: Include <machine/spl.h> and ! 108: * <linux_emul.h>, instead of i386-dependent header files, and ! 109: * moved to ... ! 110: * * linux/dev/glue/net.c: ... here. ! 111: * * linux/dev/arch/i386/glue/misc.c: Remove `x86' and moved to ... ! 112: * * linux/dev/glue/misc.c: ... here. ! 113: * * linux/dev/arch/i386/glue/kmem.c: Moved to ... ! 114: * * linux/dev/glue/kmem.c: ... here. ! 115: * ! 116: */ ! 117: ! 118: #define AUTOPROBE_IRQ ! 119: #define AUTOSENSE ! 120: ! 121: #include <linux/config.h> ! 122: ! 123: #ifdef CONFIG_SCSI_GENERIC_NCR53C400 ! 124: #define NCR53C400_PSEUDO_DMA 1 ! 125: #define PSEUDO_DMA ! 126: #define NCR53C400 ! 127: #define NCR5380_STATS ! 128: #undef NCR5380_STAT_LIMIT ! 129: #endif ! 130: #if defined(CONFIG_SCSI_G_NCR5380_PORT) && defined(CONFIG_SCSI_G_NCR5380_MEM) ! 131: #error You can not configure the Generic NCR 5380 SCSI Driver for memory mapped I/O and port mapped I/O at the same time (yet) ! 132: #endif ! 133: #if !defined(CONFIG_SCSI_G_NCR5380_PORT) && !defined(CONFIG_SCSI_G_NCR5380_MEM) ! 134: #error You must configure the Generic NCR 5380 SCSI Driver for one of memory mapped I/O and port mapped I/O. ! 135: #endif ! 136: ! 137: #include <asm/system.h> ! 138: #include <asm/io.h> ! 139: #include <linux/signal.h> ! 140: #include <linux/sched.h> ! 141: #include <linux/blk.h> ! 142: #include "scsi.h" ! 143: #include "hosts.h" ! 144: #include "g_NCR5380.h" ! 145: #include "NCR5380.h" ! 146: #include "constants.h" ! 147: #include "sd.h" ! 148: #include<linux/stat.h> ! 149: ! 150: struct proc_dir_entry proc_scsi_g_ncr5380 = { ! 151: PROC_SCSI_GENERIC_NCR5380, 9, "g_NCR5380", ! 152: S_IFDIR | S_IRUGO | S_IXUGO, 2 ! 153: }; ! 154: ! 155: #define NCR_NOT_SET 0 ! 156: static int ncr_irq=NCR_NOT_SET; ! 157: static int ncr_dma=NCR_NOT_SET; ! 158: static int ncr_addr=NCR_NOT_SET; ! 159: static int ncr_5380=NCR_NOT_SET; ! 160: static int ncr_53c400=NCR_NOT_SET; ! 161: ! 162: static struct override { ! 163: NCR5380_implementation_fields; ! 164: int irq; ! 165: int dma; ! 166: int board; /* Use NCR53c400, Ricoh, etc. extensions ? */ ! 167: } overrides ! 168: #ifdef GENERIC_NCR5380_OVERRIDE ! 169: [] = GENERIC_NCR5380_OVERRIDE ! 170: #else ! 171: [1] = {{0,},}; ! 172: #endif ! 173: ! 174: #define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override)) ! 175: ! 176: /* ! 177: * Function : static internal_setup(int board, char *str, int *ints) ! 178: * ! 179: * Purpose : LILO command line initialization of the overrides array, ! 180: * ! 181: * Inputs : board - either BOARD_NCR5380 for a normal NCR5380 board, ! 182: * or BOARD_NCR53C400 for a NCR53C400 board. str - unused, ints - ! 183: * array of integer parameters with ints[0] equal to the number of ints. ! 184: * ! 185: */ ! 186: ! 187: static void internal_setup(int board, char *str, int *ints) { ! 188: static int commandline_current = 0; ! 189: switch (board) { ! 190: case BOARD_NCR5380: ! 191: if (ints[0] != 2 && ints[0] != 3) { ! 192: printk("generic_NCR5380_setup : usage ncr5380=" STRVAL(NCR5380_map_name) ",irq,dma\n"); ! 193: return; ! 194: } ! 195: case BOARD_NCR53C400: ! 196: if (ints[0] != 2) { ! 197: printk("generic_NCR53C400_setup : usage ncr53c400=" STRVAL(NCR5380_map_name) ",irq\n"); ! 198: return; ! 199: } ! 200: } ! 201: ! 202: if (commandline_current < NO_OVERRIDES) { ! 203: overrides[commandline_current].NCR5380_map_name = (NCR5380_map_type)ints[1]; ! 204: overrides[commandline_current].irq = ints[2]; ! 205: if (ints[0] == 3) ! 206: overrides[commandline_current].dma = ints[3]; ! 207: else ! 208: overrides[commandline_current].dma = DMA_NONE; ! 209: overrides[commandline_current].board = board; ! 210: ++commandline_current; ! 211: } ! 212: } ! 213: ! 214: /* ! 215: * Function : generic_NCR5380_setup (char *str, int *ints) ! 216: * ! 217: * Purpose : LILO command line initialization of the overrides array, ! 218: * ! 219: * Inputs : str - unused, ints - array of integer parameters with ints[0] ! 220: * equal to the number of ints. ! 221: */ ! 222: ! 223: void generic_NCR5380_setup (char *str, int *ints) { ! 224: internal_setup (BOARD_NCR5380, str, ints); ! 225: } ! 226: ! 227: /* ! 228: * Function : generic_NCR53C400_setup (char *str, int *ints) ! 229: * ! 230: * Purpose : LILO command line initialization of the overrides array, ! 231: * ! 232: * Inputs : str - unused, ints - array of integer parameters with ints[0] ! 233: * equal to the number of ints. ! 234: */ ! 235: ! 236: void generic_NCR53C400_setup (char *str, int *ints) { ! 237: internal_setup (BOARD_NCR53C400, str, ints); ! 238: } ! 239: ! 240: /* ! 241: * Function : int generic_NCR5380_detect(Scsi_Host_Template * tpnt) ! 242: * ! 243: * Purpose : initializes generic NCR5380 driver based on the ! 244: * command line / compile time port and irq definitions. ! 245: * ! 246: * Inputs : tpnt - template for this SCSI adapter. ! 247: * ! 248: * Returns : 1 if a host adapter was found, 0 if not. ! 249: * ! 250: */ ! 251: ! 252: int generic_NCR5380_detect(Scsi_Host_Template * tpnt) { ! 253: static int current_override = 0; ! 254: int count; ! 255: int flags = 0; ! 256: struct Scsi_Host *instance; ! 257: ! 258: if (ncr_irq != NCR_NOT_SET) ! 259: overrides[0].irq=ncr_irq; ! 260: if (ncr_dma != NCR_NOT_SET) ! 261: overrides[0].dma=ncr_dma; ! 262: if (ncr_addr != NCR_NOT_SET) ! 263: overrides[0].NCR5380_map_name=(NCR5380_map_type)ncr_addr; ! 264: if (ncr_5380 != NCR_NOT_SET) ! 265: overrides[0].board=BOARD_NCR5380; ! 266: else if (ncr_53c400 != NCR_NOT_SET) ! 267: overrides[0].board=BOARD_NCR53C400; ! 268: ! 269: tpnt->proc_dir = &proc_scsi_g_ncr5380; ! 270: ! 271: for (count = 0; current_override < NO_OVERRIDES; ++current_override) { ! 272: if (!(overrides[current_override].NCR5380_map_name)) ! 273: continue; ! 274: ! 275: switch (overrides[current_override].board) { ! 276: case BOARD_NCR5380: ! 277: flags = FLAG_NO_PSEUDO_DMA; ! 278: break; ! 279: case BOARD_NCR53C400: ! 280: flags = FLAG_NCR53C400; ! 281: break; ! 282: } ! 283: ! 284: instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); ! 285: instance->NCR5380_instance_name = overrides[current_override].NCR5380_map_name; ! 286: ! 287: NCR5380_init(instance, flags); ! 288: ! 289: if (overrides[current_override].irq != IRQ_AUTO) ! 290: instance->irq = overrides[current_override].irq; ! 291: else ! 292: instance->irq = NCR5380_probe_irq(instance, 0xffff); ! 293: ! 294: if (instance->irq != IRQ_NONE) ! 295: if (request_irq(instance->irq, generic_NCR5380_intr, SA_INTERRUPT, "NCR5380", NULL)) { ! 296: printk("scsi%d : IRQ%d not free, interrupts disabled\n", ! 297: instance->host_no, instance->irq); ! 298: instance->irq = IRQ_NONE; ! 299: } ! 300: ! 301: if (instance->irq == IRQ_NONE) { ! 302: printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); ! 303: printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); ! 304: } ! 305: ! 306: printk("scsi%d : at " STRVAL(NCR5380_map_name) " 0x%x", instance->host_no, (unsigned int)instance->NCR5380_instance_name); ! 307: if (instance->irq == IRQ_NONE) ! 308: printk (" interrupts disabled"); ! 309: else ! 310: printk (" irq %d", instance->irq); ! 311: printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", ! 312: CAN_QUEUE, CMD_PER_LUN, GENERIC_NCR5380_PUBLIC_RELEASE); ! 313: NCR5380_print_options(instance); ! 314: printk("\n"); ! 315: ! 316: ++current_override; ! 317: ++count; ! 318: } ! 319: return count; ! 320: } ! 321: ! 322: const char * generic_NCR5380_info (struct Scsi_Host* host) { ! 323: static const char string[]="Generic NCR5380/53C400 Driver"; ! 324: return string; ! 325: } ! 326: ! 327: int generic_NCR5380_release_resources(struct Scsi_Host * instance) ! 328: { ! 329: NCR5380_local_declare(); ! 330: ! 331: NCR5380_setup(instance); ! 332: ! 333: if (instance->irq != IRQ_NONE) ! 334: free_irq(instance->irq, NULL); ! 335: ! 336: return 0; ! 337: } ! 338: ! 339: #ifdef BIOSPARAM ! 340: /* ! 341: * Function : int generic_NCR5380_biosparam(Disk * disk, kdev_t dev, int *ip) ! 342: * ! 343: * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for ! 344: * the specified device / size. ! 345: * ! 346: * Inputs : size = size of device in sectors (512 bytes), dev = block device ! 347: * major / minor, ip[] = {heads, sectors, cylinders} ! 348: * ! 349: * Returns : always 0 (success), initializes ip ! 350: * ! 351: */ ! 352: ! 353: /* ! 354: * XXX Most SCSI boards use this mapping, I could be incorrect. Some one ! 355: * using hard disks on a trantor should verify that this mapping corresponds ! 356: * to that used by the BIOS / ASPI driver by running the linux fdisk program ! 357: * and matching the H_C_S coordinates to what DOS uses. ! 358: */ ! 359: ! 360: int generic_NCR5380_biosparam(Disk * disk, kdev_t dev, int *ip) ! 361: { ! 362: int size = disk->capacity; ! 363: ip[0] = 64; ! 364: ip[1] = 32; ! 365: ip[2] = size >> 11; ! 366: return 0; ! 367: } ! 368: #endif ! 369: ! 370: #if NCR53C400_PSEUDO_DMA ! 371: static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, int len) ! 372: { ! 373: int blocks = len / 128; ! 374: int start = 0; ! 375: int i; ! 376: int bl; ! 377: NCR5380_local_declare(); ! 378: ! 379: NCR5380_setup(instance); ! 380: ! 381: #if (NDEBUG & NDEBUG_C400_PREAD) ! 382: printk("53C400r: About to read %d blocks for %d bytes\n", blocks, len); ! 383: #endif ! 384: ! 385: NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE | CSR_TRANS_DIR); ! 386: NCR5380_write(C400_BLOCK_COUNTER_REG, blocks); ! 387: while (1) { ! 388: ! 389: #if (NDEBUG & NDEBUG_C400_PREAD) ! 390: printk("53C400r: %d blocks left\n", blocks); ! 391: #endif ! 392: ! 393: if ((bl=NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) { ! 394: #if (NDEBUG & NDEBUG_C400_PREAD) ! 395: if (blocks) ! 396: printk("53C400r: blocks still == %d\n", blocks); ! 397: else ! 398: printk("53C400r: Exiting loop\n"); ! 399: #endif ! 400: break; ! 401: } ! 402: ! 403: #if 1 ! 404: if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) { ! 405: printk("53C400r: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks); ! 406: return -1; ! 407: } ! 408: #endif ! 409: ! 410: #if (NDEBUG & NDEBUG_C400_PREAD) ! 411: printk("53C400r: Waiting for buffer, bl=%d\n", bl); ! 412: #endif ! 413: ! 414: while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) ! 415: ; ! 416: #if (NDEBUG & NDEBUG_C400_PREAD) ! 417: printk("53C400r: Transferring 128 bytes\n"); ! 418: #endif ! 419: ! 420: #ifdef CONFIG_SCSI_G_NCR5380_PORT ! 421: for (i=0; i<128; i++) ! 422: dst[start+i] = NCR5380_read(C400_HOST_BUFFER); ! 423: #else ! 424: /* implies CONFIG_SCSI_G_NCR5380_MEM */ ! 425: memmove(dst+start,NCR53C400_host_buffer+NCR5380_map_name,128); ! 426: #endif ! 427: start+=128; ! 428: blocks--; ! 429: } ! 430: ! 431: if (blocks) { ! 432: #if (NDEBUG & NDEBUG_C400_PREAD) ! 433: printk("53C400r: EXTRA: Waiting for buffer\n"); ! 434: #endif ! 435: while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) ! 436: ; ! 437: ! 438: #if (NDEBUG & NDEBUG_C400_PREAD) ! 439: printk("53C400r: Transferring EXTRA 128 bytes\n"); ! 440: #endif ! 441: #ifdef CONFIG_SCSI_G_NCR5380_PORT ! 442: for (i=0; i<128; i++) ! 443: dst[start+i] = NCR5380_read(C400_HOST_BUFFER); ! 444: #else ! 445: /* implies CONFIG_SCSI_G_NCR5380_MEM */ ! 446: memmove(dst+start,NCR53C400_host_buffer+NCR5380_map_name,128); ! 447: #endif ! 448: start+=128; ! 449: blocks--; ! 450: } ! 451: #if (NDEBUG & NDEBUG_C400_PREAD) ! 452: else ! 453: printk("53C400r: No EXTRA required\n"); ! 454: #endif ! 455: ! 456: #if (NDEBUG & NDEBUG_C400_PREAD) ! 457: printk("53C400r: Final values: blocks=%d start=%d\n", blocks, start); ! 458: #endif ! 459: ! 460: if (!(NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ)) ! 461: printk("53C400r: no 53C80 gated irq after transfer"); ! 462: #if (NDEBUG & NDEBUG_C400_PREAD) ! 463: else ! 464: printk("53C400r: Got 53C80 interrupt and tried to clear it\n"); ! 465: #endif ! 466: ! 467: /* DON'T DO THIS - THEY NEVER ARRIVE! ! 468: printk("53C400r: Waiting for 53C80 registers\n"); ! 469: while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG) ! 470: ; ! 471: */ ! 472: ! 473: if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) ! 474: printk("53C400r: no end dma signal\n"); ! 475: #if (NDEBUG & NDEBUG_C400_PREAD) ! 476: else ! 477: printk("53C400r: end dma as expected\n"); ! 478: #endif ! 479: ! 480: NCR5380_write(MODE_REG, MR_BASE); ! 481: NCR5380_read(RESET_PARITY_INTERRUPT_REG); ! 482: return 0; ! 483: } ! 484: ! 485: static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src, int len) ! 486: { ! 487: int blocks = len / 128; ! 488: int start = 0; ! 489: int i; ! 490: int bl; ! 491: NCR5380_local_declare(); ! 492: ! 493: NCR5380_setup(instance); ! 494: ! 495: #if (NDEBUG & NDEBUG_C400_PWRITE) ! 496: printk("53C400w: About to write %d blocks for %d bytes\n", blocks, len); ! 497: #endif ! 498: ! 499: NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE); ! 500: NCR5380_write(C400_BLOCK_COUNTER_REG, blocks); ! 501: while (1) { ! 502: if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) { ! 503: printk("53C400w: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks); ! 504: return -1; ! 505: } ! 506: ! 507: if ((bl=NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) { ! 508: #if (NDEBUG & NDEBUG_C400_PWRITE) ! 509: if (blocks) ! 510: printk("53C400w: exiting loop, blocks still == %d\n", blocks); ! 511: else ! 512: printk("53C400w: exiting loop\n"); ! 513: #endif ! 514: break; ! 515: } ! 516: ! 517: #if (NDEBUG & NDEBUG_C400_PWRITE) ! 518: printk("53C400w: %d blocks left\n", blocks); ! 519: ! 520: printk("53C400w: waiting for buffer, bl=%d\n", bl); ! 521: #endif ! 522: while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) ! 523: ; ! 524: ! 525: #if (NDEBUG & NDEBUG_C400_PWRITE) ! 526: printk("53C400w: transferring 128 bytes\n"); ! 527: #endif ! 528: #ifdef CONFIG_SCSI_G_NCR5380_PORT ! 529: for (i=0; i<128; i++) ! 530: NCR5380_write(C400_HOST_BUFFER, src[start+i]); ! 531: #else ! 532: /* implies CONFIG_SCSI_G_NCR5380_MEM */ ! 533: memmove(NCR53C400_host_buffer+NCR5380_map_name,src+start,128); ! 534: #endif ! 535: start+=128; ! 536: blocks--; ! 537: } ! 538: if (blocks) { ! 539: #if (NDEBUG & NDEBUG_C400_PWRITE) ! 540: printk("53C400w: EXTRA waiting for buffer\n"); ! 541: #endif ! 542: while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) ! 543: ; ! 544: ! 545: #if (NDEBUG & NDEBUG_C400_PWRITE) ! 546: printk("53C400w: transferring EXTRA 128 bytes\n"); ! 547: #endif ! 548: #ifdef CONFIG_SCSI_G_NCR5380_PORT ! 549: for (i=0; i<128; i++) ! 550: NCR5380_write(C400_HOST_BUFFER, src[start+i]); ! 551: #else ! 552: /* implies CONFIG_SCSI_G_NCR5380_MEM */ ! 553: memmove(NCR53C400_host_buffer+NCR5380_map_name,src+start,128); ! 554: #endif ! 555: start+=128; ! 556: blocks--; ! 557: } ! 558: #if (NDEBUG & NDEBUG_C400_PWRITE) ! 559: else ! 560: printk("53C400w: No EXTRA required\n"); ! 561: #endif ! 562: ! 563: #if (NDEBUG & NDEBUG_C400_PWRITE) ! 564: printk("53C400w: Final values: blocks=%d start=%d\n", blocks, start); ! 565: #endif ! 566: ! 567: #if 0 ! 568: printk("53C400w: waiting for registers to be available\n"); ! 569: THEY NEVER DO! ! 570: while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG) ! 571: ; ! 572: printk("53C400w: Got em\n"); ! 573: #endif ! 574: ! 575: /* Let's wait for this instead - could be ugly */ ! 576: /* All documentation says to check for this. Maybe my hardware is too ! 577: * fast. Waiting for it seems to work fine! KLL ! 578: */ ! 579: while (!(i = NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ)) ! 580: ; ! 581: ! 582: /* ! 583: * I know. i is certainly != 0 here but the loop is new. See previous ! 584: * comment. ! 585: */ ! 586: if (i) { ! 587: #if (NDEBUG & NDEBUG_C400_PWRITE) ! 588: printk("53C400w: got 53C80 gated irq (last block)\n"); ! 589: #endif ! 590: if (!((i=NCR5380_read(BUS_AND_STATUS_REG)) & BASR_END_DMA_TRANSFER)) ! 591: printk("53C400w: No END OF DMA bit - WHOOPS! BASR=%0x\n",i); ! 592: #if (NDEBUG & NDEBUG_C400_PWRITE) ! 593: else ! 594: printk("53C400w: Got END OF DMA\n"); ! 595: #endif ! 596: } ! 597: else ! 598: printk("53C400w: no 53C80 gated irq after transfer (last block)\n"); ! 599: ! 600: #if 0 ! 601: if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) { ! 602: printk("53C400w: no end dma signal\n"); ! 603: } ! 604: #endif ! 605: ! 606: #if (NDEBUG & NDEBUG_C400_PWRITE) ! 607: printk("53C400w: waiting for last byte...\n"); ! 608: #endif ! 609: while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT)) ! 610: ; ! 611: ! 612: #if (NDEBUG & NDEBUG_C400_PWRITE) ! 613: printk("53C400w: got last byte.\n"); ! 614: printk("53C400w: pwrite exiting with status 0, whoopee!\n"); ! 615: #endif ! 616: return 0; ! 617: } ! 618: #endif /* PSEUDO_DMA */ ! 619: ! 620: #include "NCR5380.c" ! 621: ! 622: #define PRINTP(x) len += sprintf(buffer+len, x) ! 623: #define ANDP , ! 624: ! 625: static int sprint_opcode(char* buffer, int len, int opcode) { ! 626: int start = len; ! 627: PRINTP("0x%02x " ANDP opcode); ! 628: return len-start; ! 629: } ! 630: ! 631: static int sprint_command (char* buffer, int len, unsigned char *command) { ! 632: int i,s,start=len; ! 633: len += sprint_opcode(buffer, len, command[0]); ! 634: for ( i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i) ! 635: PRINTP("%02x " ANDP command[i]); ! 636: PRINTP("\n"); ! 637: return len-start; ! 638: } ! 639: ! 640: static int sprint_Scsi_Cmnd (char* buffer, int len, Scsi_Cmnd *cmd) { ! 641: int start = len; ! 642: PRINTP("host number %d destination target %d, lun %d\n" ANDP ! 643: cmd->host->host_no ANDP ! 644: cmd->target ANDP ! 645: cmd->lun); ! 646: PRINTP(" command = "); ! 647: len += sprint_command (buffer, len, cmd->cmnd); ! 648: return len-start; ! 649: } ! 650: ! 651: int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int length, int hostno, int inout) ! 652: { ! 653: int len = 0; ! 654: NCR5380_local_declare(); ! 655: unsigned char status; ! 656: int i; ! 657: struct Scsi_Host *scsi_ptr; ! 658: Scsi_Cmnd *ptr; ! 659: Scsi_Device *dev; ! 660: struct NCR5380_hostdata *hostdata; ! 661: ! 662: cli(); ! 663: ! 664: for (scsi_ptr = first_instance; scsi_ptr; scsi_ptr=scsi_ptr->next) ! 665: if (scsi_ptr->host_no == hostno) ! 666: break; ! 667: NCR5380_setup(scsi_ptr); ! 668: hostdata = (struct NCR5380_hostdata *)scsi_ptr->hostdata; ! 669: ! 670: PRINTP("SCSI host number %d : %s\n" ANDP scsi_ptr->host_no ANDP scsi_ptr->hostt->name); ! 671: PRINTP("Generic NCR5380 driver version %d\n" ANDP GENERIC_NCR5380_PUBLIC_RELEASE); ! 672: PRINTP("NCR5380 core version %d\n" ANDP NCR5380_PUBLIC_RELEASE); ! 673: #ifdef NCR53C400 ! 674: PRINTP("NCR53C400 extension version %d\n" ANDP NCR53C400_PUBLIC_RELEASE); ! 675: PRINTP("NCR53C400 card%s detected\n" ANDP (((struct NCR5380_hostdata *)scsi_ptr->hostdata)->flags & FLAG_NCR53C400)?"":" not"); ! 676: # if NCR53C400_PSEUDO_DMA ! 677: PRINTP("NCR53C400 pseudo DMA used\n"); ! 678: # endif ! 679: #else ! 680: PRINTP("NO NCR53C400 driver extensions\n"); ! 681: #endif ! 682: PRINTP("Using %s mapping at %s 0x%x, " ANDP STRVAL(NCR5380_map_config) ANDP STRVAL(NCR5380_map_name) ANDP scsi_ptr->NCR5380_instance_name); ! 683: if (scsi_ptr->irq == IRQ_NONE) ! 684: PRINTP("no interrupt\n"); ! 685: else ! 686: PRINTP("on interrupt %d\n" ANDP scsi_ptr->irq); ! 687: ! 688: #ifdef NCR5380_STATS ! 689: if (hostdata->connected || hostdata->issue_queue || hostdata->disconnected_queue) ! 690: PRINTP("There are commands pending, transfer rates may be crud\n"); ! 691: if (hostdata->pendingr) ! 692: PRINTP(" %d pending reads" ANDP hostdata->pendingr); ! 693: if (hostdata->pendingw) ! 694: PRINTP(" %d pending writes" ANDP hostdata->pendingw); ! 695: if (hostdata->pendingr || hostdata->pendingw) ! 696: PRINTP("\n"); ! 697: for (dev = scsi_devices; dev; dev=dev->next) { ! 698: if (dev->host == scsi_ptr) { ! 699: unsigned long br = hostdata->bytes_read[dev->id]; ! 700: unsigned long bw = hostdata->bytes_write[dev->id]; ! 701: long tr = hostdata->time_read[dev->id] / HZ; ! 702: long tw = hostdata->time_write[dev->id] / HZ; ! 703: ! 704: PRINTP(" T:%d %s " ANDP dev->id ANDP (dev->type < MAX_SCSI_DEVICE_CODE) ? scsi_device_types[(int)dev->type] : "Unknown"); ! 705: for (i=0; i<8; i++) ! 706: if (dev->vendor[i] >= 0x20) ! 707: *(buffer+(len++)) = dev->vendor[i]; ! 708: *(buffer+(len++)) = ' '; ! 709: for (i=0; i<16; i++) ! 710: if (dev->model[i] >= 0x20) ! 711: *(buffer+(len++)) = dev->model[i]; ! 712: *(buffer+(len++)) = ' '; ! 713: for (i=0; i<4; i++) ! 714: if (dev->rev[i] >= 0x20) ! 715: *(buffer+(len++)) = dev->rev[i]; ! 716: *(buffer+(len++)) = ' '; ! 717: ! 718: PRINTP("\n%10ld kb read in %5ld secs" ANDP br/1024 ANDP tr); ! 719: if (tr) ! 720: PRINTP(" @ %5ld bps" ANDP br / tr); ! 721: ! 722: PRINTP("\n%10ld kb written in %5ld secs" ANDP bw/1024 ANDP tw); ! 723: if (tw) ! 724: PRINTP(" @ %5ld bps" ANDP bw / tw); ! 725: PRINTP("\n"); ! 726: } ! 727: } ! 728: #endif ! 729: ! 730: status = NCR5380_read(STATUS_REG); ! 731: if (!(status & SR_REQ)) ! 732: PRINTP("REQ not asserted, phase unknown.\n"); ! 733: else { ! 734: for (i = 0; (phases[i].value != PHASE_UNKNOWN) && ! 735: (phases[i].value != (status & PHASE_MASK)); ++i) ! 736: ; ! 737: PRINTP("Phase %s\n" ANDP phases[i].name); ! 738: } ! 739: ! 740: if (!hostdata->connected) { ! 741: PRINTP("No currently connected command\n"); ! 742: } else { ! 743: len += sprint_Scsi_Cmnd (buffer, len, (Scsi_Cmnd *) hostdata->connected); ! 744: } ! 745: ! 746: PRINTP("issue_queue\n"); ! 747: ! 748: for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ! 749: ptr = (Scsi_Cmnd *) ptr->host_scribble) ! 750: len += sprint_Scsi_Cmnd (buffer, len, ptr); ! 751: ! 752: PRINTP("disconnected_queue\n"); ! 753: ! 754: for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ! 755: ptr = (Scsi_Cmnd *) ptr->host_scribble) ! 756: len += sprint_Scsi_Cmnd (buffer, len, ptr); ! 757: ! 758: *start = buffer + offset; ! 759: len -= offset; ! 760: if (len > length) ! 761: len = length; ! 762: sti(); ! 763: return len; ! 764: } ! 765: ! 766: #undef PRINTP ! 767: #undef ANDP ! 768: ! 769: #ifdef MODULE ! 770: /* Eventually this will go into an include file, but this will be later */ ! 771: Scsi_Host_Template driver_template = GENERIC_NCR5380; ! 772: ! 773: #include <linux/module.h> ! 774: #include "scsi_module.c" ! 775: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.