root/drivers/scsi/g_NCR5380.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. generic_NCR5380_setup
  2. generic_NCR53C400_setup
  3. generic_NCR5380_detect
  4. generic_NCR5380_info
  5. generic_NCR5380_release_resources
  6. generic_NCR5380_biosparam
  7. NCR5380_pread
  8. NCR5380_pwrite
  9. sprint_opcode
  10. sprint_command
  11. sprint_Scsi_Cmnd
  12. generic_NCR5380_proc_info

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

/* [previous][next][first][last][top][bottom][index][help] */