Annotation of Net2/arch/i386/isa/aha1542.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * (Mostly) Written by Julian Elischer ([email protected])
                      3:  * for TRW Financial Systems for use under the MACH(2.5) operating system.
                      4:  *
                      5:  * TRW Financial Systems, in accordance with their agreement with Carnegie
                      6:  * Mellon University, makes this software available to CMU to distribute
                      7:  * or use in any manner that they see fit as long as this message is kept with
                      8:  * the software. For this reason TFS also grants any other persons or
                      9:  * organisations permission to use or modify this software.
                     10:  *
                     11:  * TFS supplies this software to be publicly redistributed
                     12:  * on the understanding that TFS is not responsible for the correct
                     13:  * functioning of this software in any circumstances.
                     14:  *
1.1.1.2 ! root       15:  *     aha1542.c,v 1.12.2.2 1993/08/13 12:43:54 cgd Exp
1.1       root       16:  */
                     17: 
                     18: /*
                     19:  * HISTORY
1.1.1.2 ! root       20:  * aha1542.c,v
        !            21:  * Revision 1.12.2.2  1993/08/13  12:43:54  cgd
        !            22:  * from [email protected] (Christoph Robitschko):
        !            23:  * it seems that the bustek needs a little more time to settle down after a
        !            24:  * reset command than the adaptecs. Up to PK-0.2.3 there was a printf there
        !            25:  * that did the job quite well.
        !            26:  *
        !            27:  * Revision 1.12.2.1  1993/07/29  21:26:50  deraadt
        !            28:  * reliability fudge for dealing with drives that do scsi resets very slowly
        !            29:  * (or so it seems)
        !            30:  *
        !            31:  * Revision 1.12  1993/07/06  06:06:26  deraadt
        !            32:  * clean up code for timeout/untimeout/wakeup prototypes.
        !            33:  *
        !            34:  * Revision 1.11  1993/06/14  04:16:03  andrew
        !            35:  * Reduced bus-on time from the default of 11ms -> 9ms, to prevent floppy from
        !            36:  * becoming data-starved during simultaneous fd & scsi activity.
1.1       root       37:  *
1.1.1.2 ! root       38:  * Revision 1.10  1993/06/09  22:36:40  deraadt
        !            39:  * minor silliness related to two or more controllers
        !            40:  *
        !            41:  * Revision 1.9  1993/05/22  08:00:56  cgd
        !            42:  * add rcsids to everything and clean up headers
        !            43:  *
        !            44:  * Revision 1.8  1993/05/04  08:32:40  deraadt
        !            45:  * support for making dev->id_alive be set, this is for iostat to
        !            46:  * find disk devices. wee bit of a kludge. sub-device attach()
        !            47:  * routines must now return 1 for successful attach(), 0 otherwise.
        !            48:  * Other bsd's do this too..
        !            49:  *
        !            50:  * Revision 1.7  1993/04/19  06:02:16  mycroft
        !            51:  * Fix subtle word-size error.
        !            52:  *
        !            53:  * Revision 1.6  1993/04/15  07:57:50  deraadt
        !            54:  * ioconf changes, see previous cvs's that dumped core
        !            55:  *
        !            56:  * Revision 1.4  1993/04/12  08:17:23  deraadt
        !            57:  * new scsi subsystem.
        !            58:  * changes also in config/mkioconf.c & sys/scsi/*
1.1       root       59:  *
                     60:  * Revision 1.1  1993/03/21  18:09:54  cgd
                     61:  * after 0.2.2 "stable" patches applied
1.1.1.2 ! root       62:  *
1.1       root       63:  * Revision 1.6  1992/08/24  21:01:58  jason
                     64:  * many changes and bugfixes for osf1
                     65:  *
                     66:  * Revision 1.5  1992/07/31  01:22:03  julian
                     67:  * support improved scsi.h layout
                     68:  *
                     69:  * Revision 1.4  1992/07/25  03:11:26  julian
                     70:  * check each request fro sane flags.
                     71:  *
                     72:  * Revision 1.3  1992/07/24  00:52:45  julian
                     73:  * improved timeout handling.
                     74:  * added support for two arguments to the sd_done (or equiv) call so that
                     75:  * they can pre-queue several arguments.
                     76:  * slightly clean up error handling
                     77:  *
                     78:  * Revision 1.2  1992/07/17  22:03:54  julian
                     79:  * upgraded the timeout code.
                     80:  * added support for UIO-based i/o (as used for pmem operations)
                     81:  *
                     82:  * Revision 1.1  1992/05/27  00:51:12  balsup
                     83:  * machkern/cor merge
                     84:  */
                     85: 
                     86: /*
                     87:  * a FEW lines in this driver come from a MACH adaptec-disk driver
                     88:  * so the copyright below is included:
                     89:  *
                     90:  * Copyright 1990 by Open Software Foundation,
                     91:  * Grenoble, FRANCE
                     92:  *
                     93:  *             All Rights Reserved
                     94:  * 
                     95:  *   Permission to use, copy, modify, and distribute this software and
                     96:  * its documentation for any purpose and without fee is hereby granted,
                     97:  * provided that the above copyright notice appears in all copies and
                     98:  * that both the copyright notice and this permission notice appear in
                     99:  * supporting documentation, and that the name of OSF or Open Software
                    100:  * Foundation not be used in advertising or publicity pertaining to
                    101:  * distribution of the software without specific, written prior
                    102:  * permission.
                    103:  * 
                    104:  *   OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
                    105:  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
                    106:  * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
                    107:  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
                    108:  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
                    109:  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
                    110:  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                    111:  */
                    112: 
1.1.1.2 ! root      113: #include "aha.h"
1.1       root      114: 
1.1.1.2 ! root      115: #include "sys/types.h"
        !           116: #include "sys/param.h"
        !           117: #include "sys/systm.h"
        !           118: #include "sys/errno.h"
        !           119: #include "sys/ioctl.h"
        !           120: #include "sys/buf.h"
        !           121: #include "machine/stdarg.h"
        !           122: #include "sys/proc.h"
        !           123: #include "sys/user.h"
        !           124: #include "sys/dkbad.h"
        !           125: #include "sys/disklabel.h"
        !           126: #include "i386/isa/isa_device.h"
        !           127: #include "scsi/scsi_all.h"
        !           128: #include "scsi/scsiconf.h"
1.1       root      129: 
                    130: 
1.1.1.2 ! root      131: #ifdef DDB
1.1       root      132: int    Debugger();
1.1.1.2 ! root      133: #else  DDB
1.1       root      134: #define Debugger() panic("should call debugger here (adaptec.c)")
1.1.1.2 ! root      135: #endif DDB
1.1       root      136: 
                    137: extern int delaycount;  /* from clock setup code */
                    138: 
1.1.1.2 ! root      139: /* I/O Port Interface */
1.1       root      140: #define        AHA_BASE                aha_base[unit]
                    141: #define        AHA_CTRL_STAT_PORT      (AHA_BASE + 0x0)        /* control & status */
                    142: #define        AHA_CMD_DATA_PORT       (AHA_BASE + 0x1)        /* cmds and datas */
                    143: #define        AHA_INTR_PORT           (AHA_BASE + 0x2)        /* Intr. stat */
                    144: 
1.1.1.2 ! root      145: /* AHA_CTRL_STAT bits (write) */
1.1       root      146: #define AHA_HRST               0x80    /* Hardware reset */
                    147: #define AHA_SRST               0x40    /* Software reset */
                    148: #define AHA_IRST               0x20    /* Interrupt reset */
                    149: #define AHA_SCRST              0x10    /* SCSI bus reset */
                    150: 
1.1.1.2 ! root      151: /* AHA_CTRL_STAT bits (read) */
1.1       root      152: #define AHA_STST               0x80    /* Self test in Progress */
                    153: #define AHA_DIAGF              0x40    /* Diagnostic Failure */
                    154: #define AHA_INIT               0x20    /* Mbx Init required */
                    155: #define AHA_IDLE               0x10    /* Host Adapter Idle */
                    156: #define AHA_CDF                        0x08    /* cmd/data out port full */
                    157: #define AHA_DF                 0x04    /* Data in port full */
                    158: #define AHA_INVDCMD            0x01    /* Invalid command */
                    159: 
1.1.1.2 ! root      160: /* AHA_CMD_DATA bits (write) */
1.1       root      161: #define        AHA_NOP                 0x00    /* No operation */
                    162: #define AHA_MBX_INIT           0x01    /* Mbx initialization */
                    163: #define AHA_START_SCSI         0x02    /* start scsi command */
                    164: #define AHA_START_BIOS         0x03    /* start bios command */
                    165: #define AHA_INQUIRE            0x04    /* Adapter Inquiry */
                    166: #define AHA_MBO_INTR_EN                0x05    /* Enable MBO available interrupt */
                    167: #define AHA_SEL_TIMEOUT_SET    0x06    /* set selection time-out */
                    168: #define AHA_BUS_ON_TIME_SET    0x07    /* set bus-on time */
                    169: #define AHA_BUS_OFF_TIME_SET   0x08    /* set bus-off time */
                    170: #define AHA_SPEED_SET          0x09    /* set transfer speed */
                    171: #define AHA_DEV_GET            0x0a    /* return installed devices */
                    172: #define AHA_CONF_GET           0x0b    /* return configuration data */
                    173: #define AHA_TARGET_EN          0x0c    /* enable target mode */
                    174: #define AHA_SETUP_GET          0x0d    /* return setup data */
                    175: #define AHA_WRITE_CH2          0x1a    /* write channel 2 buffer */
                    176: #define AHA_READ_CH2           0x1b    /* read channel 2 buffer */
                    177: #define AHA_WRITE_FIFO         0x1c    /* write fifo buffer */
                    178: #define AHA_READ_FIFO          0x1d    /* read fifo buffer */
                    179: #define AHA_ECHO               0x1e    /* Echo command data */
                    180: 
                    181: struct aha_cmd_buf {
1.1.1.2 ! root      182:         u_char byte[16];
1.1       root      183: };
                    184: 
1.1.1.2 ! root      185: /* AHA_INTR_PORT bits (read) */
1.1       root      186: #define AHA_ANY_INTR           0x80    /* Any interrupt */
                    187: #define AHA_SCRD               0x08    /* SCSI reset detected */
                    188: #define AHA_HACC               0x04    /* Command complete */
                    189: #define AHA_MBOA               0x02    /* MBX out empty */
                    190: #define AHA_MBIF               0x01    /* MBX in full */
                    191: 
1.1.1.2 ! root      192: /* Mail box defs */
1.1       root      193: #define AHA_MBX_SIZE           16      /* mail box size */
                    194: 
                    195: struct aha_mbx {
                    196:        struct aha_mbx_out {
                    197:                unsigned char cmd;
                    198:                unsigned char ccb_addr[3];
1.1.1.2 ! root      199:        } mbo[AHA_MBX_SIZE];
1.1       root      200:        struct aha_mbx_in{
                    201:                unsigned char stat;
                    202:                unsigned char ccb_addr[3];
                    203:        } mbi[AHA_MBX_SIZE];
                    204: };
                    205: 
1.1.1.2 ! root      206: /* mbo.cmd values */
1.1       root      207: #define AHA_MBO_FREE   0x0     /* MBO entry is free */
                    208: #define AHA_MBO_START  0x1     /* MBO activate entry */
                    209: #define AHA_MBO_ABORT  0x2     /* MBO abort entry */
                    210: 
                    211: #define AHA_MBI_FREE   0x0     /* MBI entry is free */
                    212: #define AHA_MBI_OK     0x1     /* completed without error */
                    213: #define AHA_MBI_ABORT  0x2     /* aborted ccb */
                    214: #define AHA_MBI_UNKNOWN        0x3     /* Tried to abort invalid CCB */
                    215: #define AHA_MBI_ERROR  0x4     /* Completed with error */
                    216: 
                    217: extern struct aha_mbx aha_mbx[];
                    218: 
                    219: /* FOR OLD VERSIONS OF THE !%$@ this may have to be 16 (yuk) */
1.1.1.2 ! root      220: /* Number of scatter gather segments <= 16, allow 64 K i/o (min) */
        !           221: #define        AHA_NSEG        17
1.1       root      222: 
                    223: struct aha_ccb {
                    224:        unsigned char   opcode;
                    225:        unsigned char   lun:3;
                    226:        unsigned char   data_in:1;              /* must be 0 */
                    227:        unsigned char   data_out:1;             /* must be 0 */
                    228:        unsigned char   target:3;
                    229:        unsigned char   scsi_cmd_length;
                    230:        unsigned char   req_sense_length;
                    231:        unsigned char   data_length[3];
                    232:        unsigned char   data_addr[3];
                    233:        unsigned char   link_addr[3];
                    234:        unsigned char   link_id;
                    235:        unsigned char   host_stat;
                    236:        unsigned char   target_stat;
                    237:        unsigned char   reserved[2];
                    238:        struct  scsi_generic    scsi_cmd;
                    239:        struct  scsi_sense_data scsi_sense;
                    240:        struct  aha_scat_gath {
                    241:                unsigned char seg_len[3];
                    242:                unsigned char seg_addr[3];
                    243:        } scat_gath[AHA_NSEG];
1.1.1.2 ! root      244:        struct  aha_ccb  *next;
        !           245:        struct  scsi_xfer        *xfer;         /* the scsi_xfer for this cmd */
        !           246:        struct  aha_mbx_out      *mbx;          /* pointer to mail box */
1.1       root      247:        long int        delta;  /* difference from previous*/
1.1.1.2 ! root      248:        struct  aha_ccb  *later,*sooner;
1.1       root      249:        int     flags;
1.1.1.2 ! root      250: };
        !           251: 
        !           252: /* flags value? */
1.1       root      253: #define CCB_FREE        0
                    254: #define CCB_ACTIVE      1
                    255: #define CCB_ABORTED     2
                    256: 
1.1.1.2 ! root      257: struct aha_ccb *aha_soonest = (struct  aha_ccb *)0;
        !           258: struct aha_ccb *aha_latest = (struct  aha_ccb *)0;
        !           259: long int aha_furtherest = 0;   /* longest time in the timeout queue */
1.1       root      260: 
1.1.1.2 ! root      261: /* opcode fields */
1.1       root      262: #define AHA_INITIATOR_CCB      0x00    /* SCSI Initiator CCB */
                    263: #define AHA_TARGET_CCB         0x01    /* SCSI Target CCB */
                    264: #define AHA_INIT_SCAT_GATH_CCB 0x02    /* SCSI Initiator with scattter gather*/
                    265: #define AHA_RESET_CCB          0x81    /* SCSI Bus reset */
                    266: 
                    267: 
1.1.1.2 ! root      268: /* aha_ccb.host_stat values */
1.1       root      269: #define AHA_OK         0x00    /* cmd ok */
                    270: #define AHA_LINK_OK    0x0a    /* Link cmd ok */
                    271: #define AHA_LINK_IT    0x0b    /* Link cmd ok + int */
                    272: #define AHA_SEL_TIMEOUT        0x11    /* Selection time out */
                    273: #define AHA_OVER_UNDER 0x12    /* Data over/under run */
                    274: #define AHA_BUS_FREE   0x13    /* Bus dropped at unexpected time */
                    275: #define AHA_INV_BUS    0x14    /* Invalid bus phase/sequence */
                    276: #define AHA_BAD_MBO    0x15    /* Incorrect MBO cmd */
                    277: #define AHA_BAD_CCB    0x16    /* Incorrect ccb opcode */
                    278: #define AHA_BAD_LINK   0x17    /* Not same values of LUN for links */
                    279: #define AHA_INV_TARGET 0x18    /* Invalid target direction */
                    280: #define AHA_CCB_DUP    0x19    /* Duplicate CCB received */
                    281: #define AHA_INV_CCB    0x1a    /* Invalid CCB or segment list */
                    282: #define AHA_ABORTED      42
                    283: 
1.1.1.2 ! root      284: struct aha_setup {
1.1       root      285:        u_char  sync_neg:1;
                    286:        u_char  parity:1;
                    287:        u_char  :6;
                    288:        u_char  speed;
                    289:        u_char  bus_on;
                    290:        u_char  bus_off;
                    291:        u_char  num_mbx;
                    292:        u_char  mbx[3];
1.1.1.2 ! root      293:        struct {
1.1       root      294:                u_char  offset:4;
                    295:                u_char  period:3;
                    296:                u_char  valid:1;
1.1.1.2 ! root      297:        } sync[8];
1.1       root      298:        u_char  disc_sts;
                    299: };
                    300: 
1.1.1.2 ! root      301: struct aha_config {
1.1       root      302:        u_char  chan;
                    303:        u_char  intr;
                    304:        u_char  scsi_dev:3;
                    305:        u_char  :5;
                    306: };
                    307: 
                    308: #define INT9   0x01
                    309: #define INT10  0x02
                    310: #define INT11  0x04
                    311: #define INT12  0x08
                    312: #define INT14  0x20
                    313: #define INT15  0x40
                    314: 
                    315: #define CHAN0  0x01
                    316: #define CHAN5  0x20
                    317: #define CHAN6  0x40
                    318: #define CHAN7  0x80
                    319: 
                    320: 
                    321: 
                    322: #define PHYSTOKV(x)    (x | 0xFE000000)
                    323: #define KVTOPHYS(x)    vtophys(x)
                    324: #define        AHA_DMA_PAGES   AHA_NSEG
                    325: 
                    326: #define PAGESIZ        4096
                    327: #define INVALIDATE_CACHE {asm volatile( ".byte 0x0F ;.byte 0x08" ); }
                    328: 
1.1.1.2 ! root      329: struct scsi_xfer aha_scsi_xfer[NAHA];
        !           330: struct isa_device *ahainfo[NAHA];
        !           331: struct aha_mbx aha_mbx[NAHA];
        !           332: struct aha_ccb *aha_ccb_free[NAHA];
        !           333: struct aha_ccb aha_ccb[NAHA][AHA_MBX_SIZE];
        !           334: struct aha_ccb *aha_get_ccb();
        !           335: u_char aha_scratch_buf[256];
        !           336: short aha_base[NAHA];          /* base port for each board */
        !           337: int speed[NAHA];
        !           338: int aha_int[NAHA];
        !           339: int aha_dma[NAHA];
        !           340: int aha_scsi_dev[NAHA];
        !           341: int aha_initialized[NAHA];
1.1       root      342: 
1.1.1.2 ! root      343: int aha_debug = 0;
        !           344: static int ahaunit = 0;
1.1       root      345: 
                    346: #define aha_abortmbx(mbx) \
                    347:        (mbx)->cmd = AHA_MBO_ABORT; \
                    348:        outb(AHA_CMD_DATA_PORT, AHA_START_SCSI);
                    349: #define aha_startmbx(mbx) \
                    350:        (mbx)->cmd = AHA_MBO_START; \
                    351:        outb(AHA_CMD_DATA_PORT, AHA_START_SCSI);
                    352: 
1.1.1.2 ! root      353: #define AHA_CMD_TIMEOUT_FUDGE  200     /* multiplied to get Secs        */
        !           354: #define AHA_RESET_TIMEOUT      1000000 /* time to wait for reset        */
        !           355: #define AHA_SCSI_TIMEOUT_FUDGE 20      /* divided by for mSecs          */
        !           356: 
        !           357: 
        !           358: int aha_cmd(int, int, int, int, u_char *, ...);
        !           359: int ahaprobe(struct isa_device *);
        !           360: int ahaattach(struct isa_device *);
        !           361: long int aha_adapter_info(int);
        !           362: int ahaintr(int);
        !           363: void aha_free_ccb(int, struct aha_ccb *, int);
        !           364: struct aha_ccb * aha_get_ccb(int, int);
        !           365: int aha_done(int, struct aha_ccb *);
        !           366: int aha_init(int);
        !           367: void ahaminphys(struct buf *);
        !           368: int aha_scsi_cmd(struct scsi_xfer *);
        !           369: int aha_set_bus_speed(int);
        !           370: int aha_bus_speed_check(int, int);
        !           371: void aha_add_timeout(struct aha_ccb *, int);
        !           372: void aha_remove_timeout(struct aha_ccb *);
        !           373: void aha_timeout(int);
        !           374: 
        !           375: 
        !           376: struct isa_driver ahadriver = {
        !           377:        ahaprobe,
        !           378:        ahaattach,
        !           379:        "aha"
        !           380: };
1.1       root      381: 
1.1.1.2 ! root      382: struct scsi_switch aha_switch = {
        !           383:        "aha",
1.1       root      384:        aha_scsi_cmd,
                    385:        ahaminphys,
                    386:        0,
                    387:        0,
                    388:        aha_adapter_info,
1.1.1.2 ! root      389:        0, 0, 0
        !           390: };
        !           391: 
        !           392: /*
        !           393:  * aha_cmd(unit, icnt, ocnt,wait, retval, ...)
        !           394:  * Activate Adapter command
        !           395:  *     icnt:   number of args (outbound bytes written after opcode)
        !           396:  *     ocnt:   number of expected returned bytes
        !           397:  *     wait:   number of seconds to wait for response
        !           398:  *     retval: buffer where to place returned bytes
        !           399:  *     ...:    opcode AHA_NOP, AHA_MBX_INIT, AHA_START_SCSI & parameters
        !           400:  *
        !           401:  * Performs an adapter command through the ports. Not to be confused
        !           402:  *     with a scsi command, which is read in via the dma
        !           403:  * One of the adapter commands tells it to read in a scsi command
        !           404:  */
        !           405: int
        !           406: aha_cmd(int unit, int icnt, int ocnt, int wait, u_char *retval, ...)
1.1       root      407: {
1.1.1.2 ! root      408:        va_list ap;
        !           409:        int opc, sts;
1.1       root      410:        u_char oc;
                    411:        register i;
                    412: 
1.1.1.2 ! root      413:        va_start(ap, retval);
        !           414:        opc = (u_char)va_arg(ap, int);
        !           415:        /*printf("command: %08x %02x\n", opc, (u_char)opc);*/
        !           416: 
        !           417:        /*
        !           418:         * multiply the wait argument by a big constant
        !           419:         * zero defaults to 1
        !           420:         */
        !           421:        if(!wait)
        !           422:                wait = AHA_CMD_TIMEOUT_FUDGE * delaycount;
1.1       root      423:        else
1.1.1.2 ! root      424:                wait *= AHA_CMD_TIMEOUT_FUDGE * delaycount;
        !           425:        /*
        !           426:         * Wait for the adapter to go idle, unless it's one of
        !           427:         * the commands which don't need this
        !           428:         */
        !           429:        if (opc != AHA_MBX_INIT && opc != AHA_START_SCSI) {
        !           430:                i = AHA_CMD_TIMEOUT_FUDGE * delaycount; /* 1 sec?*/
        !           431:                while (--i) {
1.1       root      432:                        sts = inb(AHA_CTRL_STAT_PORT);
                    433:                        if (sts & AHA_IDLE)
                    434:                                break;
                    435:                }
1.1.1.2 ! root      436:                if (!i) {
        !           437:                        printf("aha_cmd: aha1542 host not idle(0x%x)\n", sts);
1.1       root      438:                        return(ENXIO);
                    439:                }
                    440:        }
1.1.1.2 ! root      441:        /*
        !           442:         * Now that it is idle, if we expect output, preflush the*
        !           443:         * queue feeding to us.
        !           444:         */
        !           445:        if (ocnt) {
1.1       root      446:                while((inb(AHA_CTRL_STAT_PORT)) & AHA_DF)
                    447:                        inb(AHA_CMD_DATA_PORT);
                    448:        }
1.1.1.2 ! root      449: 
        !           450:        /*
        !           451:         * Output the command and the number of arguments given
        !           452:         * for each byte, first check the port is empty.
        !           453:         */
1.1       root      454:        icnt++;         /* include the command */
1.1.1.2 ! root      455:        while (icnt--) {
1.1       root      456:                sts = inb(AHA_CTRL_STAT_PORT);
1.1.1.2 ! root      457:                for (i=0; i< wait; i++) {
1.1       root      458:                        sts = inb(AHA_CTRL_STAT_PORT);
                    459:                        if (!(sts & AHA_CDF))
                    460:                                break;
                    461:                }
1.1.1.2 ! root      462:                if (i >=  wait) {
1.1       root      463:                        printf("aha_cmd: aha1542 cmd/data port full\n");
                    464:                        outb(AHA_CTRL_STAT_PORT, AHA_SRST); 
                    465:                        return(ENXIO);
                    466:                }
1.1.1.2 ! root      467:                outb(AHA_CMD_DATA_PORT, (u_char)opc);
        !           468:                if(icnt) {
        !           469:                        opc = (u_char)va_arg(ap, int);
        !           470:                        /*printf("extra: %08x %02x\n", opc, (u_char)opc);*/
        !           471:                }
1.1       root      472:        }
1.1.1.2 ! root      473:        va_end(ap);
        !           474: 
        !           475:        /*
        !           476:         * If we expect input, loop that many times, each time,
        !           477:         * looking for the data register to have valid data
        !           478:         */
        !           479:        while (ocnt--) {
1.1       root      480:                sts = inb(AHA_CTRL_STAT_PORT);
1.1.1.2 ! root      481:                for (i=0; i< wait; i++) {
1.1       root      482:                        sts = inb(AHA_CTRL_STAT_PORT);
                    483:                        if (sts  & AHA_DF)
                    484:                                break;
                    485:                }
1.1.1.2 ! root      486:                if (i >=  wait) {
1.1       root      487:                        printf("aha_cmd: aha1542 cmd/data port empty %d\n",ocnt);
                    488:                        return(ENXIO);
                    489:                }
                    490:                oc = inb(AHA_CMD_DATA_PORT);
                    491:                if (retval)
1.1.1.2 ! root      492:                         *retval++ = oc;
1.1       root      493:        }
1.1.1.2 ! root      494:        /*
        !           495:         * Wait for the board to report a finised instruction
        !           496:         */
1.1       root      497:        i=AHA_CMD_TIMEOUT_FUDGE * delaycount;   /* 1 sec? */
1.1.1.2 ! root      498:        while (--i) {
1.1       root      499:                sts = inb(AHA_INTR_PORT);
                    500:                if (sts & AHA_HACC)
                    501:                        break;
                    502:        }
1.1.1.2 ! root      503:        if (!i) {
1.1       root      504:                printf("aha_cmd: aha1542 host not finished(0x%x)\n",sts);
                    505:                return(ENXIO);
                    506:        }
                    507:        outb(AHA_CTRL_STAT_PORT, AHA_IRST);
                    508:        return(0);
                    509: }
                    510: 
1.1.1.2 ! root      511: /*
        !           512:  * Check if the device can be found at the port given
        !           513:  * and if so, set it up ready for further work
        !           514:  * as an argument, takes the isa_device structure from
        !           515:  * autoconf.c
        !           516:  */
        !           517: int
        !           518: ahaprobe(struct isa_device *dev)
1.1       root      519: {
                    520:        int     unit = ahaunit;
1.1.1.2 ! root      521: 
        !           522:        dev->id_unit = unit;
        !           523:        aha_base[unit] = dev->id_iobase;
        !           524:        if(unit >= NAHA) {
1.1       root      525:                printf("aha: unit number (%d) too high\n",unit);
                    526:                return(0);
                    527:        }
1.1.1.2 ! root      528: 
        !           529:        /*
        !           530:         * Try initialise a unit at this location
        !           531:         * sets up dma and bus speed, loads aha_int[unit]
        !           532:         */
1.1       root      533:        if (aha_init(unit) != 0)
                    534:                return(0);
                    535: 
1.1.1.2 ! root      536:        /*
        !           537:         * If it's there, put in it's interrupt vectors
        !           538:         */
1.1       root      539:        dev->id_irq = (1 << aha_int[unit]);
                    540:        dev->id_drq = aha_dma[unit];
1.1.1.2 ! root      541:        ahaunit++;
        !           542:        return(8);
1.1       root      543: }
                    544: 
1.1.1.2 ! root      545: /*
        !           546:  * Attach all the sub-devices we can find
        !           547:  */
        !           548: int
        !           549: ahaattach(struct isa_device *dev)
1.1       root      550: {
1.1.1.2 ! root      551:        static int firsttime;
        !           552:        static u_long speedprint;       /* max 32 aha controllers */
        !           553:        int masunit = dev->id_masunit;
        !           554:        int r;
        !           555: 
        !           556:        if(!(speedprint & (1<<masunit))) {
        !           557:                DELAY(1000000);
        !           558:                speedprint |= (1<<masunit);
        !           559:                printf("aha%d: bus speed %dns\n", masunit, speed[masunit]);
        !           560:        }
        !           561: 
        !           562:        r = scsi_attach(masunit, aha_scsi_dev[masunit], &aha_switch,
        !           563:                &dev->id_physid, &dev->id_unit, dev->id_flags);
        !           564: 
        !           565:        /* only one for all boards */
        !           566:        if(firsttime==0) {
        !           567:                firsttime = 1;
1.1       root      568:                aha_timeout(0);
                    569:        }
1.1.1.2 ! root      570:        return r;
1.1       root      571: }
                    572: 
                    573: 
1.1.1.2 ! root      574: /*
        !           575:  * Return some information to the caller about
        !           576:  * the adapter and it's capabilities
        !           577:  */
        !           578: long int
        !           579: aha_adapter_info(int unit)
1.1       root      580: {
                    581:        return(2);      /* 2 outstanding requests at a time per device */
                    582: }
                    583: 
1.1.1.2 ! root      584: /*
        !           585:  * Catch an interrupt from the adaptor
        !           586:  */
        !           587: int
        !           588: ahaintr(int unit)
1.1       root      589: {
                    590:        struct aha_ccb *ccb;
                    591:        unsigned char stat;
                    592:        register i;
                    593: 
                    594:        if(scsi_debug & PRINTROUTINES)
                    595:                printf("ahaintr ");
1.1.1.2 ! root      596:        /*
        !           597:         * First acknowlege the interrupt, Then if it's
        !           598:         * not telling about a completed operation
        !           599:         * just return. 
        !           600:         */
1.1       root      601:        stat = inb(AHA_INTR_PORT);
                    602:        outb(AHA_CTRL_STAT_PORT, AHA_IRST);
                    603:        if(scsi_debug & TRACEINTERRUPTS)
                    604:                printf("int ");
                    605:        if (! (stat & AHA_MBIF))
                    606:                return(1);
                    607:        if(scsi_debug & TRACEINTERRUPTS)
                    608:                printf("b ");
1.1.1.2 ! root      609: 
        !           610:        /*
        !           611:         * If it IS then process the competed operation
        !           612:         */
        !           613:        for (i = 0; i < AHA_MBX_SIZE; i++) {
        !           614:                if (aha_mbx[unit].mbi[i].stat != AHA_MBI_FREE) {
1.1       root      615:                        ccb = (struct aha_ccb *)PHYSTOKV(
                    616:                                (_3btol(aha_mbx[unit].mbi[i].ccb_addr)));
1.1.1.2 ! root      617:                        if((stat =  aha_mbx[unit].mbi[i].stat) != AHA_MBI_OK) {
        !           618:                                switch(stat) {
        !           619:                                case AHA_MBI_ABORT:
1.1       root      620:                                        if(aha_debug)
                    621:                                            printf("abort");
                    622:                                        ccb->host_stat = AHA_ABORTED;
                    623:                                        break;
1.1.1.2 ! root      624:                                case AHA_MBI_UNKNOWN:
1.1       root      625:                                        ccb = (struct aha_ccb *)0;
                    626:                                        if(aha_debug)
                    627:                                             printf("unknown ccb for abort ");
                    628:                                        /* may have missed it */
                    629:                                        /* no such ccb known for abort */
                    630:                                        break;
1.1.1.2 ! root      631:                                case AHA_MBI_ERROR:
        !           632:                                        break;
1.1       root      633:                                default:
                    634:                                        panic("Impossible mbxi status");
                    635:                                }
1.1.1.2 ! root      636:                                if( aha_debug && ccb ) {
        !           637:                                        u_char   *cp;
1.1       root      638:                                        cp = (u_char *)(&(ccb->scsi_cmd));
                    639:                                        printf("op=%x %x %x %x %x %x\n", 
                    640:                                                cp[0], cp[1], cp[2],
                    641:                                                cp[3], cp[4], cp[5]);
                    642:                                        printf("stat %x for mbi[%d]\n"
                    643:                                                , aha_mbx[unit].mbi[i].stat, i);
                    644:                                        printf("addr = 0x%x\n", ccb);
                    645:                                }
                    646:                        }
1.1.1.2 ! root      647:                        if(ccb) {
1.1       root      648:                                aha_remove_timeout(ccb);
                    649:                                aha_done(unit,ccb);
                    650:                        }
                    651:                        aha_mbx[unit].mbi[i].stat = AHA_MBI_FREE;
                    652:                }
                    653:        }
                    654:        return(1);
                    655: }
                    656: 
1.1.1.2 ! root      657: /*
        !           658:  * A ccb (and hence a mbx-out is put onto the 
        !           659:  * free list.
        !           660:  */
        !           661: void
        !           662: aha_free_ccb(int unit, struct aha_ccb *ccb, int flags)
1.1       root      663: {
                    664:        unsigned int opri;
1.1.1.2 ! root      665: 
1.1       root      666:        if(scsi_debug & PRINTROUTINES)
                    667:                printf("ccb%d(0x%x)> ",unit,flags);
                    668:        if (!(flags & SCSI_NOMASK)) 
                    669:                opri = splbio();
                    670: 
                    671:        ccb->next = aha_ccb_free[unit];
                    672:        aha_ccb_free[unit] = ccb;
                    673:        ccb->flags = CCB_FREE;
1.1.1.2 ! root      674:        if(ccb->sooner || ccb->later) {
1.1       root      675:                printf("yikes, still in timeout queue\n");
                    676:                aha_remove_timeout(ccb);
                    677:        }
1.1.1.2 ! root      678:        /*
        !           679:         * If there were none, wake abybody waiting for
        !           680:         * one to come free, starting with queued entries*
        !           681:         */
        !           682:        if (!ccb->next)
        !           683:                wakeup( (caddr_t)&aha_ccb_free[unit]);
1.1       root      684:        if (!(flags & SCSI_NOMASK)) 
                    685:                splx(opri);
                    686: }
                    687: 
1.1.1.2 ! root      688: /*
        !           689:  * Get a free ccb (and hence mbox-out entry)
        !           690:  */
1.1       root      691: struct aha_ccb *
1.1.1.2 ! root      692: aha_get_ccb(int unit, int flags)
1.1       root      693: {
                    694:        unsigned opri;
                    695:        struct aha_ccb *rc;
                    696: 
                    697:        if(scsi_debug & PRINTROUTINES)
                    698:                printf("<ccb%d(0x%x) ",unit,flags);
                    699:        if (!(flags & SCSI_NOMASK)) 
                    700:                opri = splbio();
1.1.1.2 ! root      701:        /*
        !           702:         * If we can and have to, sleep waiting for one
        !           703:         * to come free
        !           704:         */
1.1       root      705:        while ((!(rc = aha_ccb_free[unit])) && (!(flags & SCSI_NOSLEEP)))
1.1.1.2 ! root      706:                sleep((caddr_t)&aha_ccb_free[unit], PRIBIO);
        !           707:        if (rc) {
1.1       root      708:                aha_ccb_free[unit] = aha_ccb_free[unit]->next;
                    709:                rc->flags = CCB_ACTIVE;
                    710:        }
                    711:        if (!(flags & SCSI_NOMASK)) 
                    712:                splx(opri);
                    713:        return(rc);
                    714: }
                    715: 
1.1.1.2 ! root      716: 
        !           717: /*
        !           718:  * We have a ccb which has been processed by the
        !           719:  * adaptor, now we look to see how the operation
        !           720:  * went. Wake up the owner if waiting
        !           721:  */
        !           722: int
        !           723: aha_done(int unit, struct aha_ccb *ccb)
1.1       root      724: {
                    725:        struct  scsi_sense_data *s1,*s2;
                    726:        struct  scsi_xfer *xs = ccb->xfer;
                    727: 
                    728:        if(scsi_debug & PRINTROUTINES )
                    729:                printf("aha_done ");
1.1.1.2 ! root      730:        /*
        !           731:         * Otherwise, put the results of the operation
        !           732:         * into the xfer and call whoever started it
        !           733:         */
        !           734:        if(!(xs->flags & INUSE)) {
1.1       root      735:                printf("exiting but not in use! ");
                    736:                Debugger();
                    737:        }
1.1.1.2 ! root      738:        if ((ccb->host_stat != AHA_OK || ccb->target_stat != SCSI_OK)
        !           739:            && (!(xs->flags & SCSI_ERR_OK))) {
        !           740:                s1 = (struct scsi_sense_data *)(((char *)(&ccb->scsi_cmd))
        !           741:                        + ccb->scsi_cmd_length);
1.1       root      742:                s2 = &(xs->sense);
                    743: 
1.1.1.2 ! root      744:                if(ccb->host_stat) {
        !           745:                        switch(ccb->host_stat) {
        !           746:                        case AHA_ABORTED:
        !           747:                        case AHA_SEL_TIMEOUT:   /* No response */
1.1       root      748:                                xs->error = XS_TIMEOUT;
                    749:                                break;
                    750:                        default:        /* Other scsi protocol messes */
                    751:                                xs->error = XS_DRIVER_STUFFUP;
                    752:                                if (aha_debug > 1)
1.1.1.2 ! root      753:                                        printf("host_stat%x\n", ccb->host_stat);
1.1       root      754:                        }
                    755: 
1.1.1.2 ! root      756:                } else {
        !           757:                        switch(ccb->target_stat) {
1.1       root      758:                        case 0x02:
                    759:                                /* structure copy!!!!!*/
1.1.1.2 ! root      760:                                 *s2=*s1;
1.1       root      761:                                xs->error = XS_SENSE;
                    762:                                break;
                    763:                        case 0x08:
                    764:                                xs->error = XS_BUSY;
                    765:                                break;
                    766:                        default:
                    767:                                if (aha_debug > 1)
1.1.1.2 ! root      768:                                        printf("target_stat%x\n", ccb->target_stat);
1.1       root      769:                                xs->error = XS_DRIVER_STUFFUP;
                    770:                        }
                    771:                }
1.1.1.2 ! root      772:        } else
1.1       root      773:                xs->resid = 0;
1.1.1.2 ! root      774: 
1.1       root      775:        xs->flags |= ITSDONE;
                    776:        aha_free_ccb(unit,ccb, xs->flags);
                    777:        if(xs->when_done)
                    778:                (*(xs->when_done))(xs->done_arg,xs->done_arg2);
                    779: }
                    780: 
                    781: 
1.1.1.2 ! root      782: /*
        !           783:  * Start the board, ready for normal operation
        !           784:  */
        !           785: int
        !           786: aha_init(int unit)
1.1       root      787: {
1.1.1.2 ! root      788:        struct aha_config conf;
1.1       root      789:        unsigned char ad[3];
                    790:        volatile int i,sts;
                    791: 
1.1.1.2 ! root      792:        /*
        !           793:         * reset board, If it doesn't respond, assume
        !           794:         * that it's not there.. good for the probe
        !           795:         */
1.1       root      796: 
                    797:        outb(AHA_CTRL_STAT_PORT, AHA_HRST|AHA_SRST);
                    798: 
1.1.1.2 ! root      799:        for (i=0; i < AHA_RESET_TIMEOUT; i++) {
1.1       root      800:                sts = inb(AHA_CTRL_STAT_PORT) ;
1.1.1.2 ! root      801:                if(sts == (AHA_IDLE | AHA_INIT))
1.1       root      802:                        break;
                    803:        }
1.1.1.2 ! root      804: 
        !           805:        if (i >= AHA_RESET_TIMEOUT) {
1.1       root      806:                if (aha_debug)
                    807:                        printf("aha_init: No answer from adaptec board\n");
                    808:                return(ENXIO);
                    809:        }
                    810: 
1.1.1.2 ! root      811:        /*
        !           812:         * Assume we have a board at this stage
        !           813:         * setup dma channel from jumpers and save int level
        !           814:         */
        !           815:        DELAY(1000);
        !           816:        aha_cmd(unit, 0, sizeof(conf), 0, (u_char *)&conf, AHA_CONF_GET);
        !           817:        switch(conf.chan) {
        !           818:        case CHAN0:
1.1       root      819:                outb(0x0b, 0x0c);
                    820:                outb(0x0a, 0x00);
                    821:                aha_dma[unit] = 0;
                    822:                break;
1.1.1.2 ! root      823:        case CHAN5:
1.1       root      824:                outb(0xd6, 0xc1);
                    825:                outb(0xd4, 0x01);
                    826:                aha_dma[unit] = 5;
                    827:                break;
1.1.1.2 ! root      828:        case CHAN6:
1.1       root      829:                outb(0xd6, 0xc2);
                    830:                outb(0xd4, 0x02);
                    831:                aha_dma[unit] = 6;
                    832:                break;
1.1.1.2 ! root      833:        case CHAN7:
1.1       root      834:                outb(0xd6, 0xc3);
                    835:                outb(0xd4, 0x03);
                    836:                aha_dma[unit] = 7;
                    837:                break;
                    838:        default:
                    839:                printf("illegal dma jumper setting\n");
                    840:                return(EIO);
                    841:        }
1.1.1.2 ! root      842: 
        !           843:        switch(conf.intr) {
        !           844:        case INT9:
1.1       root      845:                aha_int[unit] = 9;
                    846:                break;
1.1.1.2 ! root      847:        case INT10:
1.1       root      848:                aha_int[unit] = 10;
                    849:                break;
1.1.1.2 ! root      850:        case INT11:
1.1       root      851:                aha_int[unit] = 11;
                    852:                break;
1.1.1.2 ! root      853:        case INT12:
1.1       root      854:                aha_int[unit] = 12;
                    855:                break;
1.1.1.2 ! root      856:        case INT14:
1.1       root      857:                aha_int[unit] = 14;
                    858:                break;
1.1.1.2 ! root      859:        case INT15:
1.1       root      860:                aha_int[unit] = 15;
                    861:                break;
                    862:        default:
                    863:                printf("illegal int jumper setting\n");
                    864:                return(EIO);
                    865:        }
                    866:        /* who are we on the scsi bus */
                    867:        aha_scsi_dev[unit] = conf.scsi_dev;
                    868: 
                    869: 
1.1.1.2 ! root      870:        /*
        !           871:         * Initialize memory transfer speed
        !           872:         */
        !           873:        speed[unit] = aha_set_bus_speed(unit);
        !           874:        if(speed[unit] == 0) {
        !           875:                printf("aha%d found, but unable to talk to it correctly\n");
1.1       root      876:                return(EIO);
                    877:        }
                    878: 
1.1.1.2 ! root      879:        /*
        !           880:         * Initialize bus-on time
        !           881:         *
        !           882:         * The default is 11ms, which can result in the fd driver becoming
        !           883:         * starved for data during simultaneous fd & scsi transfers.  We
        !           884:         * set it to 9ms - if this still gives you trouble, set to 6 (ms)
        !           885:         * and work your way up.
        !           886:         */
        !           887:        aha_cmd(unit,1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 9);
        !           888: 
        !           889:        /*
        !           890:         * Initialize mail box
        !           891:         */
1.1       root      892:        lto3b(KVTOPHYS(&aha_mbx[unit]), ad);
                    893: 
1.1.1.2 ! root      894:        aha_cmd(unit, 4, 0, 0, (u_char *)0, AHA_MBX_INIT, AHA_MBX_SIZE,
        !           895:                ad[0], ad[1], ad[2]);
1.1       root      896: 
                    897: 
1.1.1.2 ! root      898:        /*
        !           899:         * link the ccb's with the mbox-out entries and
        !           900:         * into a free-list
        !           901:         */
1.1       root      902:        for (i=0; i < AHA_MBX_SIZE; i++) {
                    903:                aha_ccb[unit][i].next = aha_ccb_free[unit];
                    904:                aha_ccb_free[unit] = &aha_ccb[unit][i];
                    905:                aha_ccb_free[unit]->flags = CCB_FREE;
                    906:                aha_ccb_free[unit]->mbx = &aha_mbx[unit].mbo[i];
                    907:                lto3b(KVTOPHYS(aha_ccb_free[unit]), aha_mbx[unit].mbo[i].ccb_addr);
                    908:        }
                    909: 
1.1.1.2 ! root      910:        /*
        !           911:         * Note that we are going and return (to probe)
        !           912:         */
1.1       root      913:        aha_initialized[unit]++;
                    914:        return(0);
                    915: }
                    916: 
1.1.1.2 ! root      917: /*
        !           918:  * aha seems to explode with 17 segs (64k may require 17 segs)
        !           919:  * on old boards so use a max of 16 segs if you have problems
        !           920:  * here
        !           921:  */
        !           922: void
        !           923: ahaminphys(struct buf *bp)
1.1       root      924: {
                    925:        if(bp->b_bcount > ((AHA_NSEG - 1) * PAGESIZ))
                    926:                bp->b_bcount = ((AHA_NSEG - 1) * PAGESIZ);
                    927: }
1.1.1.2 ! root      928: 
        !           929: /*
        !           930:  * start a scsi operation given the command and
        !           931:  * the data address. Also needs the unit, target
        !           932:  * and lu
        !           933:  */
        !           934: int
        !           935: aha_scsi_cmd(struct scsi_xfer *xs)
1.1       root      936: {
                    937:        struct  scsi_sense_data *s1,*s2;
                    938:        struct aha_ccb *ccb;
                    939:        struct aha_scat_gath *sg;
                    940:        int     seg;    /* scatter gather seg being worked on */
                    941:        int i   = 0;
                    942:        int rc  =  0;
                    943:        int     thiskv;
                    944:        int     thisphys,nextphys;
                    945:        int     unit =xs->adapter;
                    946:        int     bytes_this_seg,bytes_this_page,datalen,flags;
1.1.1.2 ! root      947:        struct  iovec    *iovp;
1.1       root      948:        int     s;
                    949: 
                    950:        if(scsi_debug & PRINTROUTINES)
                    951:                printf("aha_scsi_cmd ");
1.1.1.2 ! root      952:        /*
        !           953:         * get a ccb (mbox-out) to use. If the transfer
        !           954:         * is from a buf (possibly from interrupt time)
        !           955:         * then we can't allow it to sleep
        !           956:         */
1.1       root      957:        flags = xs->flags;
1.1.1.2 ! root      958:        if(!(flags & INUSE)) {
1.1       root      959:                printf("not in use!");
                    960:                Debugger();
                    961:                xs->flags |= INUSE;
                    962:        }
1.1.1.2 ! root      963:        if(flags & ITSDONE) {
1.1       root      964:                printf("Already done! check device retry code ");
                    965:                Debugger();
                    966:                xs->flags &= ~ITSDONE;
                    967:        }
                    968:        if(xs->bp) flags |= (SCSI_NOSLEEP); /* just to be sure */
1.1.1.2 ! root      969:        if (!(ccb = aha_get_ccb(unit,flags))) {
1.1       root      970:                xs->error = XS_DRIVER_STUFFUP;
                    971:                return(TRY_AGAIN_LATER);
                    972:        }
                    973: 
                    974:        if (ccb->mbx->cmd != AHA_MBO_FREE)
                    975:                printf("MBO not free\n");
                    976: 
1.1.1.2 ! root      977:        /*
        !           978:         * Put all the arguments for the xfer in the ccb
        !           979:         * (can't use S/G if zero length)
        !           980:         */
        !           981:        ccb->xfer = xs;
1.1       root      982:        if(flags & SCSI_RESET)
1.1.1.2 ! root      983:                ccb->opcode = AHA_RESET_CCB;
1.1       root      984:        else
1.1.1.2 ! root      985:                ccb->opcode = (xs->datalen ? AHA_INIT_SCAT_GATH_CCB : AHA_INITIATOR_CCB);
        !           986:        ccb->target = xs->targ;;
        !           987:        ccb->data_out = 0;
        !           988:        ccb->data_in = 0;
        !           989:        ccb->lun = xs->lu;
        !           990:        ccb->scsi_cmd_length = xs->cmdlen;
        !           991:        ccb->req_sense_length = sizeof(ccb->scsi_sense);
        !           992: 
        !           993:        /* can use S/G only if not zero length */
        !           994:        if((xs->datalen) && (!(flags & SCSI_RESET))) {
        !           995:                lto3b(KVTOPHYS(ccb->scat_gath), ccb->data_addr);
        !           996:                sg = ccb->scat_gath;
        !           997:                seg = 0;
        !           998:                if(flags & SCSI_DATA_UIO) {
1.1       root      999:                        iovp = ((struct uio *)xs->data)->uio_iov;
                   1000:                        datalen = ((struct uio *)xs->data)->uio_iovcnt;
1.1.1.2 ! root     1001:                        while ((datalen) && (seg < AHA_NSEG)) {
        !          1002:                                lto3b((u_long)iovp->iov_base, (u_char *)&sg->seg_addr);
        !          1003:                                lto3b(iovp->iov_len, (u_char *)&sg->seg_len);
1.1       root     1004:                                if(scsi_debug & SHOWSCATGATH)
1.1.1.2 ! root     1005:                                        printf("(0x%x@0x%x)", iovp->iov_len,
        !          1006:                                                iovp->iov_base);
1.1       root     1007:                                sg++;
                   1008:                                iovp++;
                   1009:                                seg++;
                   1010:                                datalen--;
                   1011:                        }
1.1.1.2 ! root     1012:                } else {
        !          1013:                        /*
        !          1014:                         * Set up the scatter gather block
        !          1015:                         */
1.1       root     1016:                        if(scsi_debug & SHOWSCATGATH)
1.1.1.2 ! root     1017:                                printf("%d @0x%x:- ", xs->datalen, xs->data);
        !          1018:                        datalen = xs->datalen;
        !          1019:                        thiskv = (int)xs->data;
        !          1020:                        thisphys = KVTOPHYS(thiskv);
        !          1021: 
        !          1022:                        while ((datalen) && (seg < AHA_NSEG)) {
1.1       root     1023:                                bytes_this_seg  = 0;
1.1.1.2 ! root     1024: 
1.1       root     1025:                                /* put in the base address */
1.1.1.2 ! root     1026:                                lto3b(thisphys, (u_char *)&(sg->seg_addr));
        !          1027: 
1.1       root     1028:                                if(scsi_debug & SHOWSCATGATH)
                   1029:                                        printf("0x%x",thisphys);
1.1.1.2 ! root     1030: 
1.1       root     1031:                                /* do it at least once */
1.1.1.2 ! root     1032:                                nextphys = thisphys;
        !          1033:                                while ((datalen) && (thisphys == nextphys)) {
        !          1034:                                        /*
        !          1035:                                         * This page is contiguous (physically)
        !          1036:                                         * with the the last, just extend the
        !          1037:                                         * length
        !          1038:                                         */
        !          1039:                                        /* how far to the end of the page? */
1.1       root     1040:                                        nextphys = (thisphys & (~(PAGESIZ - 1)))
                   1041:                                                                + PAGESIZ;
1.1.1.2 ! root     1042:                                        bytes_this_page =
        !          1043:                                                min(nextphys - thisphys, datalen);
        !          1044:                                        bytes_this_seg += bytes_this_page;
        !          1045:                                        datalen -= bytes_this_page;
        !          1046: 
1.1       root     1047:                                        thiskv  = (thiskv & (~(PAGESIZ - 1)))
                   1048:                                                                + PAGESIZ;
                   1049:                                        if(datalen)
                   1050:                                                thisphys = KVTOPHYS(thiskv);
                   1051:                                }
1.1.1.2 ! root     1052:                                /*
        !          1053:                                 * next page isn't contiguous, finish the seg
        !          1054:                                 */
1.1       root     1055:                                if(scsi_debug & SHOWSCATGATH)
                   1056:                                        printf("(0x%x)",bytes_this_seg);
1.1.1.2 ! root     1057:                                lto3b(bytes_this_seg, (u_char *)&(sg->seg_len));
1.1       root     1058:                                sg++;
                   1059:                                seg++;
                   1060:                        }
                   1061:                }
1.1.1.2 ! root     1062:                lto3b(seg * sizeof(struct aha_scat_gath), ccb->data_length);
1.1       root     1063:                if(scsi_debug & SHOWSCATGATH)
                   1064:                        printf("\n");
1.1.1.2 ! root     1065:                if (datalen) {
        !          1066:                        /* there's still data, must have run out of segs! */
        !          1067:                        printf("aha_scsi_cmd%d: needed more than %d DMA segs, %d\n",
        !          1068:                                unit, AHA_NSEG, datalen);
1.1       root     1069:                        xs->error = XS_DRIVER_STUFFUP;
1.1.1.2 ! root     1070:                        aha_free_ccb(unit, ccb, flags);
1.1       root     1071:                        return(HAD_ERROR);
                   1072:                }
1.1.1.2 ! root     1073:        } else {        /* No data xfer, use non S/G values */
1.1       root     1074:                lto3b(0, ccb->data_addr );
1.1.1.2 ! root     1075:                lto3b(0, ccb->data_length);
1.1       root     1076:        }
1.1.1.2 ! root     1077:        lto3b(0, ccb->link_addr);
        !          1078:        /*
        !          1079:         * Put the scsi command in the ccb and start it
        !          1080:         */
1.1       root     1081:        if(!(flags & SCSI_RESET))
                   1082:                bcopy(xs->cmd, &ccb->scsi_cmd, ccb->scsi_cmd_length);
                   1083:        if(scsi_debug & SHOWCOMMANDS)
                   1084:        {
1.1.1.2 ! root     1085:                u_char   *b = (u_char *)&ccb->scsi_cmd;
1.1       root     1086:                if(!(flags & SCSI_RESET))
                   1087:                {
                   1088:                        int i = 0;
                   1089:                        printf("aha%d:%d:%d-"
                   1090:                                ,unit
                   1091:                                ,ccb->target
                   1092:                                ,ccb->lun );
                   1093:                                while(i < ccb->scsi_cmd_length )
                   1094:                                {
                   1095:                                        if(i) printf(",");
                   1096:                                         printf("%x",b[i++]);
                   1097:                                }
                   1098:                }
                   1099:                else
                   1100:                {
                   1101:                        printf("aha%d:%d:%d-RESET- " 
                   1102:                                ,unit 
                   1103:                                ,ccb->target
                   1104:                                ,ccb->lun
                   1105:                        );
                   1106:                }
                   1107:        }
                   1108:        if (!(flags & SCSI_NOMASK))
                   1109:        {
                   1110:                s= splbio(); /* stop instant timeouts */
                   1111:                aha_add_timeout(ccb,xs->timeout);
                   1112:                aha_startmbx(ccb->mbx);
1.1.1.2 ! root     1113:                /*
        !          1114:                 * Usually return SUCCESSFULLY QUEUED
        !          1115:                 */
1.1       root     1116:                splx(s);
                   1117:                if(scsi_debug & TRACEINTERRUPTS)
                   1118:                        printf("sent ");
                   1119:                return(SUCCESSFULLY_QUEUED);
                   1120:        }
                   1121:        aha_startmbx(ccb->mbx);
                   1122:        if(scsi_debug & TRACEINTERRUPTS)
                   1123:                printf("cmd_sent, waiting ");
1.1.1.2 ! root     1124:        /*
        !          1125:         * If we can't use interrupts, poll on completion*
        !          1126:         */
1.1       root     1127:        {
                   1128:                int done = 0;
                   1129:                int count = delaycount * xs->timeout / AHA_SCSI_TIMEOUT_FUDGE;
                   1130:                while((!done) && count)
                   1131:                {
                   1132:                        i=0;
                   1133:                        while ( (!done) && i<AHA_MBX_SIZE)
                   1134:                        {
                   1135:                                if ((aha_mbx[unit].mbi[i].stat != AHA_MBI_FREE )
                   1136:                                   && (PHYSTOKV(_3btol(aha_mbx[unit].mbi[i].ccb_addr)
                   1137:                                        == (int)ccb)))
                   1138:                                {
                   1139:                                        aha_mbx[unit].mbi[i].stat = AHA_MBI_FREE;
                   1140:                                        aha_done(unit,ccb);
                   1141:                                        done++;
                   1142:                                }
                   1143:                                i++;
                   1144:                        }
                   1145:                        count--;
                   1146:                }
                   1147:                if (!count)
                   1148:                {
                   1149:                        if (!(xs->flags & SCSI_SILENT))
                   1150:                                printf("cmd fail\n");
                   1151:                        aha_abortmbx(ccb->mbx);
                   1152:                        count = delaycount * 2000 / AHA_SCSI_TIMEOUT_FUDGE;
1.1.1.2 ! root     1153:                        while((!done) && count) {
1.1       root     1154:                                i=0;
1.1.1.2 ! root     1155:                                while ( (!done) && i<AHA_MBX_SIZE) {
1.1       root     1156:                                        if ((aha_mbx[unit].mbi[i].stat != AHA_MBI_FREE )
1.1.1.2 ! root     1157:                                            && (PHYSTOKV(_3btol(aha_mbx[unit].mbi[i].ccb_addr)
        !          1158:                                                == (int)ccb))) {
1.1       root     1159:                                                aha_mbx[unit].mbi[i].stat = AHA_MBI_FREE;
                   1160:                                                aha_done(unit,ccb);
                   1161:                                                done++;
                   1162:                                        }
                   1163:                                        i++;
                   1164:                                }
                   1165:                                count--;
                   1166:                        }
1.1.1.2 ! root     1167:                        if(!count) {
1.1       root     1168:                                printf("abort failed in wait\n");
                   1169:                                ccb->mbx->cmd = AHA_MBO_FREE;
                   1170:                        }
                   1171:                        aha_free_ccb(unit,ccb,flags);
                   1172:                        ahaintr(unit);
                   1173:                        xs->error = XS_DRIVER_STUFFUP;
                   1174:                        return(HAD_ERROR);
                   1175:                }
                   1176:                ahaintr(unit);
                   1177:                if(xs->error) return(HAD_ERROR);
                   1178:                return(COMPLETE);
                   1179:        } 
1.1.1.2 ! root     1180:        /* return ??? */
1.1       root     1181: }
                   1182: 
1.1.1.2 ! root     1183: /*
        !          1184:  * try each speed in turn, when we find one that works, use
        !          1185:  * the NEXT one for a safety margin, unless that doesn't exist
        !          1186:  * or doesn't work. returns the nsec value of the time used
        !          1187:  * or 0 if it could get a working speed ( or the NEXT speed 
        !          1188:  * failed)
        !          1189:  * Go one slower to be safe, unless eisa at 100 ns.. trust it
        !          1190:  */
        !          1191: int
        !          1192: aha_set_bus_speed(int unit)
1.1       root     1193: {
1.1.1.2 ! root     1194:        int retval, retval2;
        !          1195:        int speed;
1.1       root     1196: 
                   1197: #ifdef EISA
                   1198:        speed = 0; /* start at the fastest */
                   1199: #else  EISA
                   1200:        speed = 1; /* 100 ns can crash some ISA busses (!?!) */
                   1201: #endif EISA
1.1.1.2 ! root     1202:        while (1) {
        !          1203:                retval = aha_bus_speed_check(unit, speed);
        !          1204:                if(retval == HAD_ERROR) {
1.1       root     1205:                        printf("no working bus speed!!!\n");
1.1.1.2 ! root     1206:                        return 0;
1.1       root     1207:                }
1.1.1.2 ! root     1208: 
1.1       root     1209:                if(retval == 0)
                   1210:                        speed++;
1.1.1.2 ! root     1211:                else {
1.1       root     1212:                        if(speed != 0)
                   1213:                                speed++;
1.1.1.2 ! root     1214: 
        !          1215:                        /*printf("%d nsec ok, but using ", retval);*/
        !          1216:                        retval2 = aha_bus_speed_check(unit, speed);
        !          1217:                        if(retval2 == HAD_ERROR) {
        !          1218:                                /*printf("marginal ");*/
1.1       root     1219:                                retval2 = retval;
                   1220:                        }
1.1.1.2 ! root     1221:                        if(retval2) {
        !          1222:                                /*printf("%d nsec\n", retval2);*/
        !          1223:                                return retval2;
        !          1224:                        } else {
        !          1225:                                /*printf(".. slower failed, abort.\n", retval);*/
        !          1226:                                return 0;
1.1       root     1227:                        }
                   1228:                }
                   1229:        }
                   1230: }
                   1231: 
1.1.1.2 ! root     1232: /*
        !          1233:  * Set the DMA speed to the Nth speed and try an xfer. If it
        !          1234:  * fails return 0, if it succeeds return the nsec value selected
        !          1235:  * If there is no such speed return HAD_ERROR.
        !          1236:  */
        !          1237: static struct bus_speed {
1.1       root     1238:        char    arg;
                   1239:        int     nsecs;
1.1.1.2 ! root     1240: } aha_bus_speeds[] = {
        !          1241:        {0x88, 100},
        !          1242:        {0x99, 150},
        !          1243:        {0xaa, 200},
        !          1244:        {0xbb, 250},
        !          1245:        {0xcc, 300},
        !          1246:        {0xdd, 350},
        !          1247:        {0xee, 400},
        !          1248:        {0xff, 450}
1.1       root     1249: };
1.1.1.2 ! root     1250: static char aha_test_string[] =
        !          1251:        "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz!@";
1.1       root     1252: 
1.1.1.2 ! root     1253: int
        !          1254: aha_bus_speed_check(int unit, int speed)
1.1       root     1255: {
                   1256:        int     numspeeds = sizeof(aha_bus_speeds)/sizeof(struct bus_speed);
                   1257:        u_char  ad[3];
                   1258: 
1.1.1.2 ! root     1259:        /*
        !          1260:         * Check we have such an entry
        !          1261:         */
1.1       root     1262:        if(speed >= numspeeds) return(HAD_ERROR);       /* illegal speed */
1.1.1.2 ! root     1263: 
        !          1264:        /*
        !          1265:         * Set the dma-speed
        !          1266:         */
        !          1267:        aha_cmd(unit,1, 0, 0, (u_char *)0, AHA_SPEED_SET,aha_bus_speeds[speed].arg);
        !          1268: 
        !          1269:        /*
        !          1270:         * put the test data into the buffer and calculate
        !          1271:         * it's address. Read it onto the board
        !          1272:         */
        !          1273:        strcpy((char *)aha_scratch_buf, (char *)aha_test_string);
        !          1274:        lto3b(KVTOPHYS(aha_scratch_buf), ad);
        !          1275: 
        !          1276:        aha_cmd(unit,3, 0, 0, (u_char *)0, AHA_WRITE_FIFO,
        !          1277:                ad[0], ad[1], ad[2]);
        !          1278: 
        !          1279:        /*
        !          1280:         * clear the buffer then copy the contents back from the
        !          1281:         * board.
        !          1282:         */
1.1       root     1283:        bzero(aha_scratch_buf,54);      /* 54 bytes transfered by test */
                   1284: 
1.1.1.2 ! root     1285:        aha_cmd(unit,3, 0, 0, (u_char *)0, AHA_READ_FIFO,
        !          1286:                ad[0], ad[1], ad[2]);
1.1       root     1287: 
1.1.1.2 ! root     1288:        /*
        !          1289:         * Compare the original data and the final data and
        !          1290:         * return the correct value depending upon the result
        !          1291:         * if copy fails.. assume too fast
        !          1292:         */
        !          1293:        if(strcmp(aha_test_string, (char *)aha_scratch_buf))
1.1       root     1294:                return(0);
1.1.1.2 ! root     1295:        return(aha_bus_speeds[speed].nsecs);
1.1       root     1296: }
                   1297: 
                   1298: 
                   1299: /*
                   1300:  *                +----------+    +----------+    +----------+
                   1301:  * aha_soonest--->|    later |--->|     later|--->|     later|-->0
                   1302:  *                | [Delta]  |    | [Delta]  |    | [Delta]  |
                   1303:  *           0<---|sooner    |<---|sooner    |<---|sooner    |<---aha_latest
                   1304:  *                +----------+    +----------+    +----------+
                   1305:  *
                   1306:  *     aha_furtherest = sum(Delta[1..n])
                   1307:  */
1.1.1.2 ! root     1308: void
        !          1309: aha_add_timeout(struct aha_ccb *ccb, int time)
1.1       root     1310: {
                   1311:        int     timeprev;
                   1312:        struct aha_ccb *prev;
                   1313:        int     s = splbio();
                   1314: 
                   1315:        if(prev = aha_latest) /* yes, an assign */
                   1316:                timeprev = aha_furtherest;
                   1317:        else
                   1318:                timeprev = 0;
1.1.1.2 ! root     1319: 
        !          1320:        while(prev && (timeprev > time)) {
1.1       root     1321:                timeprev -= prev->delta;
                   1322:                prev = prev->sooner;
                   1323:        }
1.1.1.2 ! root     1324:        if(prev) {
1.1       root     1325:                ccb->delta = time - timeprev;
1.1.1.2 ! root     1326:                if( ccb->later = prev->later) {
1.1       root     1327:                        ccb->later->sooner = ccb;
                   1328:                        ccb->later->delta -= ccb->delta;
1.1.1.2 ! root     1329:                } else {
1.1       root     1330:                        aha_furtherest = time;
                   1331:                        aha_latest = ccb;
                   1332:                }
                   1333:                ccb->sooner = prev;
                   1334:                prev->later = ccb;
1.1.1.2 ! root     1335:        } else {
        !          1336:                if( ccb->later = aha_soonest) {
1.1       root     1337:                        ccb->later->sooner = ccb;
                   1338:                        ccb->later->delta -= time;
1.1.1.2 ! root     1339:                } else {
1.1       root     1340:                        aha_furtherest = time;
                   1341:                        aha_latest = ccb;
                   1342:                }
                   1343:                ccb->delta = time;
                   1344:                ccb->sooner = (struct aha_ccb *)0;
                   1345:                aha_soonest = ccb;
                   1346:        }
                   1347:        splx(s);
                   1348: }
                   1349: 
1.1.1.2 ! root     1350: void
        !          1351: aha_remove_timeout(struct aha_ccb *ccb)
1.1       root     1352: {
                   1353:        int     s = splbio();
                   1354: 
                   1355:        if(ccb->sooner)
                   1356:                ccb->sooner->later = ccb->later;
                   1357:        else
                   1358:                aha_soonest = ccb->later;
1.1.1.2 ! root     1359: 
        !          1360:        if(ccb->later) {
1.1       root     1361:                ccb->later->sooner = ccb->sooner;
                   1362:                ccb->later->delta += ccb->delta;
1.1.1.2 ! root     1363:        } else {
1.1       root     1364:                aha_latest = ccb->sooner;
                   1365:                aha_furtherest -= ccb->delta;
                   1366:        }
                   1367:        ccb->sooner = ccb->later = (struct aha_ccb *)0;
                   1368:        splx(s);
                   1369: }
                   1370: 
                   1371: extern int     hz;
                   1372: #define ONETICK 500 /* milliseconds */
                   1373: #define SLEEPTIME ((hz * 1000) / ONETICK)
1.1.1.2 ! root     1374: 
        !          1375: void
        !          1376: aha_timeout(int arg)
1.1       root     1377: {
                   1378:        struct  aha_ccb  *ccb;
                   1379:        int     unit;
                   1380:        int     s       = splbio();
                   1381: 
1.1.1.2 ! root     1382:        while( ccb = aha_soonest ) {
        !          1383:                if(ccb->delta <= ONETICK) {
        !          1384:                        /*
        !          1385:                         * It has timed out, we need to do some work
        !          1386:                         */
1.1       root     1387:                        unit = ccb->xfer->adapter;
1.1.1.2 ! root     1388:                        printf("aha%d: device %d timed out ", unit,
        !          1389:                                ccb->xfer->targ);
1.1       root     1390: 
1.1.1.2 ! root     1391:                        /*
        !          1392:                         * Unlink it from the queue
        !          1393:                         */
1.1       root     1394:                        aha_remove_timeout(ccb);
                   1395: 
1.1.1.2 ! root     1396:                        /*
        !          1397:                         * If The ccb's mbx is not free, then
        !          1398:                         * the board has gone south
        !          1399:                         */
        !          1400:                        if(ccb->mbx->cmd != AHA_MBO_FREE) {
        !          1401:                                printf("aha%d not taking commands!\n", unit);
1.1       root     1402:                                Debugger();
                   1403:                        }
1.1.1.2 ! root     1404:                        /*
        !          1405:                         * If it has been through before, then
        !          1406:                         * a previous abort has failed, don't
        !          1407:                         * try abort again
        !          1408:                         */
        !          1409:                        if(ccb->flags == CCB_ABORTED) {
        !          1410:                                 /* abort timed out */
1.1       root     1411:                                printf(" AGAIN\n");
                   1412:                                ccb->xfer->retries = 0; /* I MEAN IT ! */
                   1413:                                ccb->host_stat = AHA_ABORTED;
                   1414:                                aha_done(unit,ccb);
1.1.1.2 ! root     1415:                        } else {
        !          1416:                                /* abort the operation that has timed out */
1.1       root     1417:                                printf("\n");
                   1418:                                aha_abortmbx(ccb->mbx);
1.1.1.2 ! root     1419:                                /* 2 secs for the abort */
1.1       root     1420:                                aha_add_timeout(ccb,2000 + ONETICK);
                   1421:                                ccb->flags = CCB_ABORTED;
                   1422:                        }
1.1.1.2 ! root     1423:                } else {
        !          1424:                        /*
        !          1425:                         * It has not timed out, adjust and leave
        !          1426:                         */
1.1       root     1427:                        ccb->delta -= ONETICK;
                   1428:                        aha_furtherest -= ONETICK;
                   1429:                        break;
                   1430:                }
                   1431:        }
                   1432:        splx(s);
1.1.1.2 ! root     1433:        timeout((timeout_t)aha_timeout, (caddr_t)arg, SLEEPTIME);
1.1       root     1434: }

unix.superglobalmegacorp.com

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