Annotation of Gnu-Mach/linux/src/drivers/scsi/g_NCR5380.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.