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