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

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

unix.superglobalmegacorp.com

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