[BACK]Return to seagate.c CVS log [TXT][DIR] Up to [local] / sys / dev / isa

Annotation of sys/dev/isa/seagate.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: seagate.c,v 1.21 2007/06/29 15:17:02 jasper Exp $     */
        !             2:
        !             3: /*
        !             4:  * ST01/02, Future Domain TMC-885, TMC-950 SCSI driver
        !             5:  *
        !             6:  * Copyright 1994, Charles Hannum (mycroft@ai.mit.edu)
        !             7:  * Copyright 1994, Kent Palmkvist (kentp@isy.liu.se)
        !             8:  * Copyright 1994, Robert Knier (rknier@qgraph.com)
        !             9:  * Copyright 1992, 1994 Drew Eckhardt (drew@colorado.edu)
        !            10:  * Copyright 1994, Julian Elischer (julian@tfs.com)
        !            11:  *
        !            12:  * Others that has contributed by example code is
        !            13:  *             Glen Overby (overby@cray.com)
        !            14:  *             Tatu Yllnen
        !            15:  *             Brian E Litzinger
        !            16:  *
        !            17:  * Redistribution and use in source and binary forms, with or without
        !            18:  * modification, are permitted provided that the following conditions
        !            19:  * are met:
        !            20:  * 1. Redistributions of source code must retain the above copyright
        !            21:  *    notice, this list of conditions and the following disclaimer.
        !            22:  * 2. Redistributions in binary form must reproduce the above copyright
        !            23:  *    notice, this list of conditions and the following disclaimer in the
        !            24:  *    documentation and/or other materials provided with the distribution.
        !            25:  *
        !            26:  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND
        !            27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE DEVELOPERS BE LIABLE
        !            30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            36:  * SUCH DAMAGE.
        !            37:  */
        !            38:
        !            39: /*
        !            40:  * kentp  940307 alpha version based on newscsi-03 version of Julians SCSI-code
        !            41:  * kentp  940314 Added possibility to not use messages
        !            42:  * rknier 940331 Added fast transfer code
        !            43:  * rknier 940407 Added assembler coded data transfers
        !            44:  */
        !            45:
        !            46: /*
        !            47:  * What should really be done:
        !            48:  *
        !            49:  * Add missing tests for timeouts
        !            50:  * Restructure interrupt enable/disable code (runs to long with int disabled)
        !            51:  * Find bug? giving problem with tape status
        !            52:  * Add code to handle Future Domain 840, 841, 880 and 881
        !            53:  * adjust timeouts (startup is very slow)
        !            54:  * add code to use tagged commands in SCSI2
        !            55:  * Add code to handle slow devices better (sleep if device not disconnecting)
        !            56:  * Fix unnecessary interrupts
        !            57:  */
        !            58:
        !            59: /*
        !            60:  * Note to users trying to share a disk between DOS and unix:
        !            61:  * The ST01/02 is a translating host-adapter. It is not giving DOS
        !            62:  * the same number of heads/tracks/sectors as specified by the disk.
        !            63:  * It is therefore important to look at what numbers DOS thinks the
        !            64:  * disk has. Use these to disklabel your disk in an appropriate manner
        !            65:  */
        !            66:
        !            67: #include <sys/types.h>
        !            68: #include <sys/param.h>
        !            69: #include <sys/systm.h>
        !            70: #include <sys/kernel.h>
        !            71: #include <sys/errno.h>
        !            72: #include <sys/ioctl.h>
        !            73: #include <sys/device.h>
        !            74: #include <sys/buf.h>
        !            75: #include <sys/proc.h>
        !            76: #include <sys/user.h>
        !            77: #include <sys/queue.h>
        !            78: #include <sys/malloc.h>
        !            79:
        !            80: #include <machine/intr.h>
        !            81: #include <machine/pio.h>
        !            82:
        !            83: #include <scsi/scsi_all.h>
        !            84: #include <scsi/scsi_message.h>
        !            85: #include <scsi/scsiconf.h>
        !            86:
        !            87: #include <dev/isa/isareg.h>
        !            88: #include <dev/isa/isavar.h>
        !            89: #include <i386/isa/isa_machdep.h>      /* XXX USES ISA HOLE DIRECTLY */
        !            90:
        !            91: #define        SEA_SCB_MAX     32      /* allow maximally 8 scsi control blocks */
        !            92: #define SCB_TABLE_SIZE 8       /* start with 8 scb entries in table */
        !            93: #define BLOCK_SIZE     512     /* size of READ/WRITE areas on SCSI card */
        !            94:
        !            95: /*
        !            96:  * defining SEA_BLINDTRANSFER will make DATA IN and DATA OUT to be done with
        !            97:  * blind transfers, i.e. no check is done for scsi phase changes. This will
        !            98:  * result in data loss if the scsi device does not send its data using
        !            99:  * BLOCK_SIZE bytes at a time.
        !           100:  * If SEA_BLINDTRANSFER defined and SEA_ASSEMBLER also defined will result in
        !           101:  * the use of blind transfers coded in assembler. SEA_ASSEMBLER is no good
        !           102:  * without SEA_BLINDTRANSFER defined.
        !           103:  */
        !           104: #define        SEA_BLINDTRANSFER       /* do blind transfers */
        !           105: #define        SEA_ASSEMBLER           /* Use assembly code for fast transfers */
        !           106:
        !           107: /*
        !           108:  * defining SEA_NOMSGS causes messages not to be used (thereby disabling
        !           109:  * disconnects)
        !           110:  */
        !           111: #undef SEA_NOMSGS
        !           112:
        !           113: /*
        !           114:  * defining SEA_NODATAOUT makes dataout phase being aborted
        !           115:  */
        !           116: #undef SEA_NODATAOUT
        !           117:
        !           118: /* Debugging definitions. Should not be used unless you want a lot of
        !           119:    printouts even under normal conditions */
        !           120:
        !           121: #undef SEA_DEBUGQUEUE          /* Display info about queue-lengths */
        !           122:
        !           123: /******************************* board definitions **************************/
        !           124: /*
        !           125:  * CONTROL defines
        !           126:  */
        !           127: #define CMD_RST                0x01            /* scsi reset */
        !           128: #define CMD_SEL                0x02            /* scsi select */
        !           129: #define CMD_BSY                0x04            /* scsi busy */
        !           130: #define        CMD_ATTN        0x08            /* scsi attention */
        !           131: #define CMD_START_ARB  0x10            /* start arbitration bit */
        !           132: #define        CMD_EN_PARITY   0x20            /* enable scsi parity generation */
        !           133: #define CMD_INTR       0x40            /* enable scsi interrupts */
        !           134: #define CMD_DRVR_ENABLE        0x80            /* scsi enable */
        !           135:
        !           136: /*
        !           137:  * STATUS
        !           138:  */
        !           139: #define STAT_BSY       0x01            /* scsi busy */
        !           140: #define STAT_MSG       0x02            /* scsi msg */
        !           141: #define STAT_IO                0x04            /* scsi I/O */
        !           142: #define STAT_CD                0x08            /* scsi C/D */
        !           143: #define STAT_REQ       0x10            /* scsi req */
        !           144: #define STAT_SEL       0x20            /* scsi select */
        !           145: #define STAT_PARITY    0x40            /* parity error bit */
        !           146: #define STAT_ARB_CMPL  0x80            /* arbitration complete bit */
        !           147:
        !           148: /*
        !           149:  * REQUESTS
        !           150:  */
        !           151: #define PH_DATAOUT     (0)
        !           152: #define PH_DATAIN      (STAT_IO)
        !           153: #define PH_CMD         (STAT_CD)
        !           154: #define PH_STAT                (STAT_CD | STAT_IO)
        !           155: #define PH_MSGOUT      (STAT_MSG | STAT_CD)
        !           156: #define PH_MSGIN       (STAT_MSG | STAT_CD | STAT_IO)
        !           157:
        !           158: #define PH_MASK                (STAT_MSG | STAT_CD | STAT_IO)
        !           159:
        !           160: #define PH_INVALID     0xff
        !           161:
        !           162: #define SEA_RAMOFFSET  0x00001800
        !           163:
        !           164: #define BASE_CMD       (CMD_INTR | CMD_EN_PARITY)
        !           165:
        !           166: #define        SEAGATE         1       /* Seagate ST0[12] */
        !           167: #define        FDOMAIN         2       /* Future Domain TMC-{885,950} */
        !           168: #define        FDOMAIN840      3       /* Future Domain TMC-{84[01],88[01]} */
        !           169:
        !           170: /******************************************************************************/
        !           171:
        !           172: /* scsi control block used to keep info about a scsi command */
        !           173: struct sea_scb {
        !           174:         u_char *data;                  /* position in data buffer so far */
        !           175:        int datalen;                    /* bytes remaining to transfer */
        !           176:        TAILQ_ENTRY(sea_scb) chain;
        !           177:        struct scsi_xfer *xs;           /* the scsi_xfer for this cmd */
        !           178:        int flags;                      /* status of the instruction */
        !           179: #define        SCB_FREE        0
        !           180: #define        SCB_ACTIVE      1
        !           181: #define SCB_ABORTED    2
        !           182: #define SCB_TIMEOUT    4
        !           183: #define SCB_ERROR      8
        !           184: };
        !           185:
        !           186: /*
        !           187:  * data structure describing current status of the scsi bus. One for each
        !           188:  * controller card.
        !           189:  */
        !           190: struct sea_softc {
        !           191:        struct device sc_dev;
        !           192:        struct isadev sc_id;
        !           193:        void *sc_ih;
        !           194:
        !           195:        int type;                       /* board type */
        !           196:        caddr_t maddr;                  /* Base address for card */
        !           197:        caddr_t maddr_cr_sr;            /* Address of control and status reg */
        !           198:        caddr_t maddr_dr;               /* Address of data register */
        !           199:
        !           200:        struct scsi_link sc_link;       /* prototype for subdevs */
        !           201:        TAILQ_HEAD(, sea_scb) free_list, ready_list, nexus_list;
        !           202:        struct sea_scb *nexus;          /* currently connected command */
        !           203:        int numscbs;                    /* number of scsi control blocks */
        !           204:        struct sea_scb scb[SCB_TABLE_SIZE];
        !           205:
        !           206:        int our_id;                     /* our scsi id */
        !           207:        u_char our_id_mask;
        !           208:        volatile u_char busy[8];        /* index=target, bit=lun, Keep track of
        !           209:                                           busy luns at device target */
        !           210: };
        !           211:
        !           212: /* flag showing if main routine is running. */
        !           213: static volatile int main_running = 0;
        !           214:
        !           215: #define        STATUS  (*(volatile u_char *)sea->maddr_cr_sr)
        !           216: #define CONTROL        STATUS
        !           217: #define DATA   (*(volatile u_char *)sea->maddr_dr)
        !           218:
        !           219: /*
        !           220:  * These are "special" values for the tag parameter passed to sea_select
        !           221:  * Not implemented right now.
        !           222:  */
        !           223: #define TAG_NEXT       -1      /* Use next free tag */
        !           224: #define TAG_NONE       -2      /*
        !           225:                                 * Establish I_T_L nexus instead of I_T_L_Q
        !           226:                                 * even on SCSI-II devices.
        !           227:                                 */
        !           228:
        !           229: typedef struct {
        !           230:        char *signature;
        !           231:        int offset, length;
        !           232:        int type;
        !           233: } BiosSignature;
        !           234:
        !           235: /*
        !           236:  * Signatures for automatic recognition of board type
        !           237:  */
        !           238: static const BiosSignature signatures[] = {
        !           239: {"ST01 v1.7  (C) Copyright 1987 Seagate", 15, 37, SEAGATE},
        !           240: {"SCSI BIOS 2.00  (C) Copyright 1987 Seagate", 15, 40, SEAGATE},
        !           241:
        !           242: /*
        !           243:  * The following two lines are NOT mistakes. One detects ROM revision
        !           244:  * 3.0.0, the other 3.2. Since seagate has only one type of SCSI adapter,
        !           245:  * and this is not going to change, the "SEAGATE" and "SCSI" together
        !           246:  * are probably "good enough"
        !           247:  */
        !           248: {"SEAGATE SCSI BIOS ", 16, 17, SEAGATE},
        !           249: {"SEAGATE SCSI BIOS ", 17, 17, SEAGATE},
        !           250:
        !           251: /*
        !           252:  * However, future domain makes several incompatible SCSI boards, so specific
        !           253:  * signatures must be used.
        !           254:  */
        !           255: {"FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89", 5, 45, FDOMAIN},
        !           256: {"FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89", 5, 46, FDOMAIN},
        !           257: {"FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90",5, 47, FDOMAIN},
        !           258: {"FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90",5, 47, FDOMAIN},
        !           259: {"FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90", 5, 46, FDOMAIN},
        !           260: {"FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92",   5, 44, FDOMAIN},
        !           261: {"FUTURE DOMAIN TMC-950",                         5, 21, FDOMAIN},
        !           262: };
        !           263:
        !           264: #define        nsignatures     (sizeof(signatures) / sizeof(signatures[0]))
        !           265:
        !           266: #ifdef notdef
        !           267: static const char *bases[] = {
        !           268:        (char *) 0xc8000, (char *) 0xca000, (char *) 0xcc000,
        !           269:        (char *) 0xce000, (char *) 0xdc000, (char *) 0xde000
        !           270: };
        !           271:
        !           272: #define        nbases          (sizeof(bases) / sizeof(bases[0]))
        !           273: #endif
        !           274:
        !           275: struct         sea_scb *sea_get_scb(struct sea_softc *, int);
        !           276: int            seaintr(void *);
        !           277: int            sea_scsi_cmd(struct scsi_xfer *);
        !           278: int            sea_poll(struct sea_softc *, struct scsi_xfer *, int);
        !           279: int            sea_select(struct sea_softc *sea, struct sea_scb *scb);
        !           280: int            sea_transfer_pio(struct sea_softc *sea, u_char *phase,
        !           281:                    int *count, u_char **data);
        !           282: int            sea_abort(struct sea_softc *, struct sea_scb *scb);
        !           283: static void    sea_main(void);
        !           284: static void    sea_information_transfer(struct sea_softc *);
        !           285: void           sea_timeout(void *);
        !           286: void           sea_done(struct sea_softc *, struct sea_scb *);
        !           287: void           sea_free_scb(struct sea_softc *, struct sea_scb *, int);
        !           288: void           sea_init(struct sea_softc *);
        !           289: void           sea_send_scb(struct sea_softc *sea, struct sea_scb *scb);
        !           290: void           sea_reselect(struct sea_softc *sea);
        !           291:
        !           292: struct scsi_adapter sea_switch = {
        !           293:        sea_scsi_cmd,
        !           294:        minphys,        /* no special minphys(), since driver uses PIO */
        !           295:        0,
        !           296:        0,
        !           297: };
        !           298:
        !           299: /* the below structure is so we have a default dev struct for our link struct */
        !           300: struct scsi_device sea_dev = {
        !           301:        NULL,           /* use default error handler */
        !           302:        NULL,           /* have a queue, served by this */
        !           303:        NULL,           /* have no async handler */
        !           304:        NULL,           /* Use default 'done' routine */
        !           305: };
        !           306:
        !           307: int    seaprobe(struct device *, void *, void *);
        !           308: void   seaattach(struct device *, struct device *, void *);
        !           309: int    seaprint(void *, const char *);
        !           310:
        !           311: struct cfattach sea_ca = {
        !           312:        sizeof(struct sea_softc), seaprobe, seaattach
        !           313: };
        !           314:
        !           315: struct cfdriver sea_cd = {
        !           316:        NULL, "sea", DV_DULL
        !           317: };
        !           318:
        !           319: #ifdef SEA_DEBUGQUEUE
        !           320: void
        !           321: sea_queue_length(struct sea_softc *sea)
        !           322: {
        !           323:        struct sea_scb *scb;
        !           324:        int connected, issued, disconnected;
        !           325:
        !           326:        connected = sea->nexus ? 1 : 0;
        !           327:        issued = 0;
        !           328:        TAILQ_FOREACH(scb, &sea->ready_list, chain)
        !           329:                issued++;
        !           330:        disconnected = 0;
        !           331:        TAILQ_FOREACH(scb, &sea->nexus_list, chain)
        !           332:                disconnected++;
        !           333:        printf("%s: length: %d/%d/%d\n", sea->sc_dev.dv_xname, connected,
        !           334:            issued, disconnected);
        !           335: }
        !           336: #endif
        !           337:
        !           338: /*
        !           339:  * Check if the device can be found at the port given and if so, detect the
        !           340:  * type the type of board.  Set it up ready for further work. Takes the isa_dev
        !           341:  * structure from autoconf as an argument.
        !           342:  * Returns 1 if card recognized, 0 if errors.
        !           343:  */
        !           344: int
        !           345: seaprobe(struct device *parent, void *match, void *aux)
        !           346: {
        !           347:        struct sea_softc *sea = match;
        !           348:        struct isa_attach_args *ia = aux;
        !           349:        int i;
        !           350:
        !           351:        /*
        !           352:         * Could try to find a board by looking through all possible addresses.
        !           353:         * This is not done the right way now, because I have not found a way
        !           354:         * to get a boards virtual memory address given its physical.  There is
        !           355:         * a function that returns the physical address for a given virtual
        !           356:         * address, but not the other way around.
        !           357:         */
        !           358:
        !           359:        if (ia->ia_maddr == MADDRUNK) {
        !           360:                /* XXX */
        !           361:                return 0;
        !           362:        } else
        !           363:                sea->maddr = ISA_HOLE_VADDR(ia->ia_maddr);
        !           364:
        !           365:        /* check board type */  /* No way to define this through config */
        !           366:        for (i = 0; i < nsignatures; i++)
        !           367:                if (!bcmp(sea->maddr + signatures[i].offset,
        !           368:                    signatures[i].signature, signatures[i].length)) {
        !           369:                        sea->type = signatures[i].type;
        !           370:                        break;
        !           371:                }
        !           372:
        !           373:        /* Find controller and data memory addresses */
        !           374:        switch (sea->type) {
        !           375:        case SEAGATE:
        !           376:        case FDOMAIN840:
        !           377:                sea->maddr_cr_sr =
        !           378:                    (void *) (((u_char *)sea->maddr) + 0x1a00);
        !           379:                sea->maddr_dr =
        !           380:                    (void *) (((u_char *)sea->maddr) + 0x1c00);
        !           381:                break;
        !           382:        case FDOMAIN:
        !           383:                sea->maddr_cr_sr =
        !           384:                    (void *) (((u_char *)sea->maddr) + 0x1c00);
        !           385:                sea->maddr_dr =
        !           386:                    (void *) (((u_char *)sea->maddr) + 0x1e00);
        !           387:                break;
        !           388:        default:
        !           389: #if 0
        !           390:                printf("%s: board type unknown at address %p\n",
        !           391:                    sea->sc_dev.dv_xname, sea->maddr);
        !           392: #endif
        !           393:                return 0;
        !           394:        }
        !           395:
        !           396:        /* Test controller RAM (works the same way on future domain cards?) */
        !           397:        *((u_char *)sea->maddr + SEA_RAMOFFSET) = 0xa5;
        !           398:        *((u_char *)sea->maddr + SEA_RAMOFFSET + 1) = 0x5a;
        !           399:
        !           400:        if ((*((u_char *)sea->maddr + SEA_RAMOFFSET) != 0xa5) ||
        !           401:            (*((u_char *)sea->maddr + SEA_RAMOFFSET + 1) != 0x5a)) {
        !           402:                printf("%s: board RAM failure\n", sea->sc_dev.dv_xname);
        !           403:                return 0;
        !           404:        }
        !           405:
        !           406:        ia->ia_drq = DRQUNK;
        !           407:        ia->ia_msize = 0x2000;
        !           408:        ia->ia_iosize = 0;
        !           409:        return 1;
        !           410: }
        !           411:
        !           412: int
        !           413: seaprint(void *aux, const char *name)
        !           414: {
        !           415:        if (name != NULL)
        !           416:                printf("%s: scsibus ", name);
        !           417:        return UNCONF;
        !           418: }
        !           419:
        !           420: /*
        !           421:  * Attach all sub-devices we can find
        !           422:  */
        !           423: void
        !           424: seaattach(struct device *parent, struct device *self, void *aux)
        !           425: {
        !           426:        struct isa_attach_args *ia = aux;
        !           427:        struct sea_softc *sea = (void *)self;
        !           428:        struct scsibus_attach_args saa;
        !           429:
        !           430:        sea_init(sea);
        !           431:
        !           432:        /*
        !           433:         * fill in the prototype scsi_link.
        !           434:         */
        !           435:        sea->sc_link.adapter_softc = sea;
        !           436:        sea->sc_link.adapter_target = sea->our_id;
        !           437:        sea->sc_link.adapter = &sea_switch;
        !           438:        sea->sc_link.device = &sea_dev;
        !           439:        sea->sc_link.openings = 1;
        !           440:
        !           441:        printf("\n");
        !           442:
        !           443:        sea->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
        !           444:            IPL_BIO, seaintr, sea, sea->sc_dev.dv_xname);
        !           445:
        !           446:        bzero(&saa, sizeof(saa));
        !           447:        saa.saa_sc_link = &sea->sc_link;
        !           448:
        !           449:        /*
        !           450:         * ask the adapter what subunits are present
        !           451:         */
        !           452:        config_found(self, &saa, seaprint);
        !           453: }
        !           454:
        !           455: /*
        !           456:  * Catch an interrupt from the adaptor
        !           457:  */
        !           458: int
        !           459: seaintr(void *arg)
        !           460: {
        !           461:        struct sea_softc *sea = arg;
        !           462:
        !           463: #ifdef DEBUG   /* extra overhead, and only needed for intr debugging */
        !           464:        if ((STATUS & STAT_PARITY) == 0 &&
        !           465:            (STATUS & (STAT_SEL | STAT_IO)) != (STAT_SEL | STAT_IO))
        !           466:                return 0;
        !           467: #endif
        !           468:
        !           469: loop:
        !           470:        /* dispatch to appropriate routine if found and done=0 */
        !           471:        /* should check to see that this card really caused the interrupt */
        !           472:
        !           473:        if (STATUS & STAT_PARITY) {
        !           474:                /* Parity error interrupt */
        !           475:                printf("%s: parity error\n", sea->sc_dev.dv_xname);
        !           476:                return 1;
        !           477:        }
        !           478:
        !           479:        if ((STATUS & (STAT_SEL | STAT_IO)) == (STAT_SEL | STAT_IO)) {
        !           480:                /* Reselect interrupt */
        !           481:                sea_reselect(sea);
        !           482:                if (!main_running)
        !           483:                        sea_main();
        !           484:                goto loop;
        !           485:        }
        !           486:
        !           487:        return 1;
        !           488: }
        !           489:
        !           490: /*
        !           491:  * Setup data structures, and reset the board and the SCSI bus.
        !           492:  */
        !           493: void
        !           494: sea_init(struct sea_softc *sea)
        !           495: {
        !           496:        int i;
        !           497:
        !           498:        /* Reset the scsi bus (I don't know if this is needed */
        !           499:        CONTROL = BASE_CMD | CMD_DRVR_ENABLE | CMD_RST;
        !           500:        delay(25);      /* hold reset for at least 25 microseconds */
        !           501:        CONTROL = BASE_CMD;
        !           502:        delay(10);      /* wait a Bus Clear Delay (800 ns + bus free delay (800 ns) */
        !           503:
        !           504:        /* Set our id (don't know anything about this) */
        !           505:        switch (sea->type) {
        !           506:        case SEAGATE:
        !           507:                sea->our_id = 7;
        !           508:                break;
        !           509:        case FDOMAIN:
        !           510:        case FDOMAIN840:
        !           511:                sea->our_id = 6;
        !           512:                break;
        !           513:        }
        !           514:        sea->our_id_mask = 1 << sea->our_id;
        !           515:
        !           516:        /* init fields used by our routines */
        !           517:        sea->nexus = 0;
        !           518:        TAILQ_INIT(&sea->ready_list);
        !           519:        TAILQ_INIT(&sea->nexus_list);
        !           520:        TAILQ_INIT(&sea->free_list);
        !           521:        for (i = 0; i < 8; i++)
        !           522:                sea->busy[i] = 0x00;
        !           523:
        !           524:        /* link up the free list of scbs */
        !           525:        sea->numscbs = SCB_TABLE_SIZE;
        !           526:        for (i = 0; i < SCB_TABLE_SIZE; i++) {
        !           527:                TAILQ_INSERT_TAIL(&sea->free_list, &sea->scb[i], chain);
        !           528:        }
        !           529: }
        !           530:
        !           531: /*
        !           532:  * start a scsi operation given the command and the data address. Also needs
        !           533:  * the unit, target and lu.
        !           534:  */
        !           535: int
        !           536: sea_scsi_cmd(struct scsi_xfer *xs)
        !           537: {
        !           538:        struct scsi_link *sc_link = xs->sc_link;
        !           539:        struct sea_softc *sea = sc_link->adapter_softc;
        !           540:        struct sea_scb *scb;
        !           541:        int flags;
        !           542:        int s;
        !           543:
        !           544:        SC_DEBUG(sc_link, SDEV_DB2, ("sea_scsi_cmd\n"));
        !           545:
        !           546:        flags = xs->flags;
        !           547:        if (flags & ITSDONE) {
        !           548:                printf("%s: done?\n", sea->sc_dev.dv_xname);
        !           549:                xs->flags &= ~ITSDONE;
        !           550:        }
        !           551:        if ((scb = sea_get_scb(sea, flags)) == NULL) {
        !           552:                return TRY_AGAIN_LATER;
        !           553:        }
        !           554:        scb->flags = SCB_ACTIVE;
        !           555:        scb->xs = xs;
        !           556:
        !           557:        if (flags & SCSI_RESET) {
        !           558:                /*
        !           559:                 * Try to send a reset command to the card.
        !           560:                 * XXX Not implemented.
        !           561:                 */
        !           562:                printf("%s: resetting\n", sea->sc_dev.dv_xname);
        !           563:                xs->error = XS_DRIVER_STUFFUP;
        !           564:                return COMPLETE;
        !           565:        }
        !           566:
        !           567:        /*
        !           568:         * Put all the arguments for the xfer in the scb
        !           569:         */
        !           570:        scb->datalen = xs->datalen;
        !           571:        scb->data = xs->data;
        !           572:
        !           573: #ifdef SEA_DEBUGQUEUE
        !           574:        sea_queue_length(sea);
        !           575: #endif
        !           576:
        !           577:        s = splbio();
        !           578:
        !           579:        sea_send_scb(sea, scb);
        !           580:
        !           581:        /*
        !           582:         * Usually return SUCCESSFULLY QUEUED
        !           583:         */
        !           584:        if ((flags & SCSI_POLL) == 0) {
        !           585:                timeout_set(&scb->xs->stimeout, sea_timeout, scb);
        !           586:                timeout_add(&scb->xs->stimeout, (xs->timeout * hz) / 1000);
        !           587:                splx(s);
        !           588:                return SUCCESSFULLY_QUEUED;
        !           589:        }
        !           590:
        !           591:        splx(s);
        !           592:
        !           593:        /*
        !           594:         * If we can't use interrupts, poll on completion
        !           595:         */
        !           596:        if (sea_poll(sea, xs, xs->timeout)) {
        !           597:                sea_timeout(scb);
        !           598:                if (sea_poll(sea, xs, 2000))
        !           599:                        sea_timeout(scb);
        !           600:        }
        !           601:        return COMPLETE;
        !           602: }
        !           603:
        !           604: /*
        !           605:  * Get a free scb. If there are none, see if we can allocate a new one.  If so,
        !           606:  * put it in the hash table too; otherwise return an error or sleep.
        !           607:  */
        !           608: struct sea_scb *
        !           609: sea_get_scb(struct sea_softc *sea, int flags)
        !           610: {
        !           611:        int s;
        !           612:        struct sea_scb *scb;
        !           613:
        !           614:        s = splbio();
        !           615:
        !           616:        /*
        !           617:         * If we can and have to, sleep waiting for one to come free
        !           618:         * but only if we can't allocate a new one.
        !           619:         */
        !           620:        for (;;) {
        !           621:                scb = TAILQ_FIRST(&sea->free_list);
        !           622:                if (scb) {
        !           623:                        TAILQ_REMOVE(&sea->free_list, scb, chain);
        !           624:                        break;
        !           625:                }
        !           626:                if (sea->numscbs < SEA_SCB_MAX) {
        !           627:                        scb = (struct sea_scb *) malloc(sizeof(struct sea_scb),
        !           628:                            M_TEMP, M_NOWAIT);
        !           629:                        if (scb) {
        !           630:                                bzero(scb, sizeof(struct sea_scb));
        !           631:                                sea->numscbs++;
        !           632:                        } else
        !           633:                                printf("%s: can't malloc scb\n",
        !           634:                                    sea->sc_dev.dv_xname);
        !           635:                        break;
        !           636:                }
        !           637:                if ((flags & SCSI_NOSLEEP) != 0)
        !           638:                        break;
        !           639:                tsleep(&sea->free_list, PRIBIO, "seascb", 0);
        !           640:        }
        !           641:
        !           642:        splx(s);
        !           643:        return scb;
        !           644: }
        !           645:
        !           646: /*
        !           647:  * Try to send this command to the board. Because this board does not use any
        !           648:  * mailboxes, this routine simply adds the command to the queue held by the
        !           649:  * sea_softc structure.
        !           650:  * A check is done to see if the command contains a REQUEST_SENSE command, and
        !           651:  * if so the command is put first in the queue, otherwise the command is added
        !           652:  * to the end of the queue. ?? Not correct ??
        !           653:  */
        !           654: void
        !           655: sea_send_scb(struct sea_softc *sea, struct sea_scb *scb)
        !           656: {
        !           657:
        !           658:        TAILQ_INSERT_TAIL(&sea->ready_list, scb, chain);
        !           659:        /* Try to do some work on the card. */
        !           660:        if (!main_running)
        !           661:                sea_main();
        !           662: }
        !           663:
        !           664: /*
        !           665:  * Coroutine that runs as long as more work can be done on the seagate host
        !           666:  * adapter in a system.  Both sea_scsi_cmd and sea_intr will try to start it in
        !           667:  * case it is not running.
        !           668:  */
        !           669: void
        !           670: sea_main(void)
        !           671: {
        !           672:        struct sea_softc *sea;
        !           673:        struct sea_scb *scb;
        !           674:        int done;
        !           675:        int unit;
        !           676:        int s;
        !           677:
        !           678:        main_running = 1;
        !           679:
        !           680:        /*
        !           681:         * This should not be run with interrupts disabled, but use the splx
        !           682:         * code instead.
        !           683:         */
        !           684: loop:
        !           685:        done = 1;
        !           686:        for (unit = 0; unit < sea_cd.cd_ndevs; unit++) {
        !           687:                sea = sea_cd.cd_devs[unit];
        !           688:                if (!sea)
        !           689:                        continue;
        !           690:                s = splbio();
        !           691:                if (!sea->nexus) {
        !           692:                        /*
        !           693:                         * Search through the ready_list for a command
        !           694:                         * destined for a target that's not busy.
        !           695:                         */
        !           696:                        TAILQ_FOREACH(scb, &sea->ready_list, chain) {
        !           697:                                if (!(sea->busy[scb->xs->sc_link->target] &
        !           698:                                    (1 << scb->xs->sc_link->lun))) {
        !           699:                                        TAILQ_REMOVE(&sea->ready_list, scb,
        !           700:                                            chain);
        !           701:
        !           702:                                        /* Re-enable interrupts. */
        !           703:                                        splx(s);
        !           704:
        !           705:                                        /*
        !           706:                                         * Attempt to establish an I_T_L nexus.
        !           707:                                         * On success, sea->nexus is set.
        !           708:                                         * On failure, we must add the command
        !           709:                                         * back to the issue queue so we can
        !           710:                                         * keep trying.
        !           711:                                         */
        !           712:
        !           713:                                        /*
        !           714:                                         * REQUEST_SENSE commands are issued
        !           715:                                         * without tagged queueing, even on
        !           716:                                         * SCSI-II devices because the
        !           717:                                         * contingent alligence condition
        !           718:                                         * exists for the entire unit.
        !           719:                                         */
        !           720:
        !           721:                                        /*
        !           722:                                         * First check that if any device has
        !           723:                                         * tried a reconnect while we have done
        !           724:                                         * other things with interrupts
        !           725:                                         * disabled.
        !           726:                                         */
        !           727:
        !           728:                                        if ((STATUS & (STAT_SEL | STAT_IO)) ==
        !           729:                                            (STAT_SEL | STAT_IO)) {
        !           730:                                                sea_reselect(sea);
        !           731:                                                break;
        !           732:                                        }
        !           733:                                        if (sea_select(sea, scb)) {
        !           734:                                                s = splbio();
        !           735:                                                TAILQ_INSERT_HEAD(&sea->ready_list,
        !           736:                                                    scb, chain);
        !           737:                                                splx(s);
        !           738:                                        } else
        !           739:                                                break;
        !           740:                                } /* if target/lun is not busy */
        !           741:                        } /* for scb */
        !           742:                        if (!sea->nexus) {
        !           743:                                /* check for reselection phase */
        !           744:                                if ((STATUS & (STAT_SEL | STAT_IO)) ==
        !           745:                                    (STAT_SEL | STAT_IO)) {
        !           746:                                        sea_reselect(sea);
        !           747:                                }
        !           748:                        }
        !           749:                } /* if (!sea->nexus) */
        !           750:
        !           751:                splx(s);
        !           752:                if (sea->nexus) {       /* we are connected. Do the task */
        !           753:                        sea_information_transfer(sea);
        !           754:                        done = 0;
        !           755:                } else
        !           756:                        break;
        !           757:        } /* for instance */
        !           758:
        !           759:        if (!done)
        !           760:                goto loop;
        !           761:
        !           762:        main_running = 0;
        !           763: }
        !           764:
        !           765: void
        !           766: sea_free_scb(struct sea_softc *sea, struct sea_scb *scb, int flags)
        !           767: {
        !           768:        int s;
        !           769:
        !           770:        s = splbio();
        !           771:
        !           772:        scb->flags = SCB_FREE;
        !           773:        TAILQ_INSERT_HEAD(&sea->free_list, scb, chain);
        !           774:
        !           775:        /*
        !           776:         * If there were none, wake anybody waiting for one to come free,
        !           777:         * starting with queued entries.
        !           778:         */
        !           779:        if (TAILQ_NEXT(scb, chain) == NULL)
        !           780:                wakeup((caddr_t)&sea->free_list);
        !           781:
        !           782:        splx(s);
        !           783: }
        !           784:
        !           785: void
        !           786: sea_timeout(void *arg)
        !           787: {
        !           788:        struct sea_scb *scb = arg;
        !           789:        struct scsi_xfer *xs = scb->xs;
        !           790:        struct scsi_link *sc_link = xs->sc_link;
        !           791:        struct sea_softc *sea = sc_link->adapter_softc;
        !           792:        int s;
        !           793:
        !           794:        sc_print_addr(sc_link);
        !           795:        printf("timed out");
        !           796:
        !           797:        s = splbio();
        !           798:
        !           799:        /*
        !           800:         * If it has been through before, then
        !           801:         * a previous abort has failed, don't
        !           802:         * try abort again
        !           803:         */
        !           804:        if (scb->flags & SCB_ABORTED) {
        !           805:                /* abort timed out */
        !           806:                printf(" AGAIN\n");
        !           807:                scb->xs->retries = 0;
        !           808:                scb->flags |= SCB_ABORTED;
        !           809:                sea_done(sea, scb);
        !           810:        } else {
        !           811:                /* abort the operation that has timed out */
        !           812:                printf("\n");
        !           813:                scb->flags |= SCB_ABORTED;
        !           814:                sea_abort(sea, scb);
        !           815:                /* 2 secs for the abort */
        !           816:                if ((xs->flags & SCSI_POLL) == 0) {
        !           817:                        timeout_set(&scb->xs->stimeout, sea_timeout, scb);
        !           818:                        timeout_add(&scb->xs->stimeout, 2 * hz);
        !           819:                }
        !           820:        }
        !           821:
        !           822:        splx(s);
        !           823: }
        !           824:
        !           825: void
        !           826: sea_reselect(struct sea_softc *sea)
        !           827: {
        !           828:        u_char target_mask;
        !           829:        int i;
        !           830:        u_char lun, phase;
        !           831:        u_char msg[3];
        !           832:        int len;
        !           833:        u_char *data;
        !           834:        struct sea_scb *scb;
        !           835:        int abort = 0;
        !           836:
        !           837:        if (!((target_mask = STATUS) & STAT_SEL)) {
        !           838:                printf("%s: wrong state 0x%x\n", sea->sc_dev.dv_xname,
        !           839:                    target_mask);
        !           840:                return;
        !           841:        }
        !           842:
        !           843:        /* wait for a device to win the reselection phase */
        !           844:        /* signals this by asserting the I/O signal */
        !           845:        for (i = 10; i && (STATUS & (STAT_SEL | STAT_IO | STAT_BSY)) !=
        !           846:            (STAT_SEL | STAT_IO | 0); i--);
        !           847:        /* !! Check for timeout here */
        !           848:        /* the data bus contains original initiator id ORed with target id */
        !           849:        target_mask = DATA;
        !           850:        /* see that we really are the initiator */
        !           851:        if (!(target_mask & sea->our_id_mask)) {
        !           852:                printf("%s: polled reselection was not for me: 0x%x\n",
        !           853:                    sea->sc_dev.dv_xname, target_mask);
        !           854:                return;
        !           855:        }
        !           856:        /* find target who won */
        !           857:        target_mask &= ~sea->our_id_mask;
        !           858:        /* host responds by asserting the BSY signal */
        !           859:        CONTROL = BASE_CMD | CMD_DRVR_ENABLE | CMD_BSY;
        !           860:        /* target should respond by deasserting the SEL signal */
        !           861:        for (i = 50000; i && (STATUS & STAT_SEL); i++);
        !           862:        /* remove the busy status */
        !           863:        CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
        !           864:        /* we are connected. Now we wait for the MSGIN condition */
        !           865:        for (i = 50000; i && !(STATUS & STAT_REQ); i--);
        !           866:        /* !! Add timeout check here */
        !           867:        /* hope we get an IDENTIFY message */
        !           868:        len = 3;
        !           869:        data = msg;
        !           870:        phase = PH_MSGIN;
        !           871:        sea_transfer_pio(sea, &phase, &len, &data);
        !           872:
        !           873:        if (MSG_ISIDENTIFY(msg[0])) {
        !           874:                printf("%s: expecting IDENTIFY message, got 0x%x\n",
        !           875:                    sea->sc_dev.dv_xname, msg[0]);
        !           876:                abort = 1;
        !           877:                scb = NULL;
        !           878:        } else {
        !           879:                lun = msg[0] & 0x07;
        !           880:
        !           881:                /*
        !           882:                 * Find the command corresponding to the I_T_L or I_T_L_Q nexus
        !           883:                 * we just reestablished, and remove it from the disconnected
        !           884:                 * queue.
        !           885:                 */
        !           886:                TAILQ_FOREACH(scb, &sea->nexus_list, chain)
        !           887:                        if (target_mask == (1 << scb->xs->sc_link->target) &&
        !           888:                            lun == scb->xs->sc_link->lun) {
        !           889:                                TAILQ_REMOVE(&sea->nexus_list, scb,
        !           890:                                    chain);
        !           891:                                break;
        !           892:                        }
        !           893:                if (!scb) {
        !           894:                        printf("%s: target %02x lun %d not disconnected\n",
        !           895:                            sea->sc_dev.dv_xname, target_mask, lun);
        !           896:                        /*
        !           897:                         * Since we have an established nexus that we can't do
        !           898:                         * anything with, we must abort it.
        !           899:                         */
        !           900:                        abort = 1;
        !           901:                }
        !           902:        }
        !           903:
        !           904:        if (abort) {
        !           905:                msg[0] = MSG_ABORT;
        !           906:                len = 1;
        !           907:                data = msg;
        !           908:                phase = PH_MSGOUT;
        !           909:                CONTROL = BASE_CMD | CMD_ATTN;
        !           910:                sea_transfer_pio(sea, &phase, &len, &data);
        !           911:        } else
        !           912:                sea->nexus = scb;
        !           913:
        !           914:        return;
        !           915: }
        !           916:
        !           917: /*
        !           918:  * Transfer data in given phase using polled I/O.
        !           919:  */
        !           920: int
        !           921: sea_transfer_pio(struct sea_softc *sea, u_char *phase, int *count, u_char **data)
        !           922: {
        !           923:        u_char p = *phase, tmp;
        !           924:        int c = *count;
        !           925:        u_char *d = *data;
        !           926:        int timeout;
        !           927:
        !           928:        do {
        !           929:                /*
        !           930:                 * Wait for assertion of REQ, after which the phase bits will
        !           931:                 * be valid.
        !           932:                 */
        !           933:                for (timeout = 0; timeout < 50000; timeout++)
        !           934:                        if ((tmp = STATUS) & STAT_REQ)
        !           935:                                break;
        !           936:                if (!(tmp & STAT_REQ)) {
        !           937:                        printf("%s: timeout waiting for STAT_REQ\n",
        !           938:                            sea->sc_dev.dv_xname);
        !           939:                        break;
        !           940:                }
        !           941:
        !           942:                /*
        !           943:                 * Check for phase mismatch.  Reached if the target decides
        !           944:                 * that it has finished the transfer.
        !           945:                 */
        !           946:                if (sea->type == FDOMAIN840)
        !           947:                        tmp = ((tmp & 0x08) >> 2) |
        !           948:                              ((tmp & 0x02) << 2) |
        !           949:                               (tmp & 0xf5);
        !           950:                if ((tmp & PH_MASK) != p)
        !           951:                        break;
        !           952:
        !           953:                /* Do actual transfer from SCSI bus to/from memory. */
        !           954:                if (!(p & STAT_IO))
        !           955:                        DATA = *d;
        !           956:                else
        !           957:                        *d = DATA;
        !           958:                ++d;
        !           959:
        !           960:                /*
        !           961:                 * The SCSI standard suggests that in MSGOUT phase, the
        !           962:                 * initiator should drop ATN on the last byte of the message
        !           963:                 * phase after REQ has been asserted for the handshake but
        !           964:                 * before the initiator raises ACK.
        !           965:                 * Don't know how to accomplish this on the ST01/02.
        !           966:                 */
        !           967:
        !           968: #if 0
        !           969:                /*
        !           970:                 * XXX
        !           971:                 * The st01 code doesn't wait for STAT_REQ to be deasserted.
        !           972:                 * Is this ok?
        !           973:                 */
        !           974:                for (timeout = 0; timeout < 200000L; timeout++)
        !           975:                        if (!(STATUS & STAT_REQ))
        !           976:                                break;
        !           977:                if (STATUS & STAT_REQ)
        !           978:                        printf("%s: timeout on wait for !STAT_REQ",
        !           979:                            sea->sc_dev.dv_xname);
        !           980: #endif
        !           981:        } while (--c);
        !           982:
        !           983:        *count = c;
        !           984:        *data = d;
        !           985:        tmp = STATUS;
        !           986:        if (tmp & STAT_REQ)
        !           987:                *phase = tmp & PH_MASK;
        !           988:        else
        !           989:                *phase = PH_INVALID;
        !           990:
        !           991:        if (c && (*phase != p))
        !           992:                return -1;
        !           993:        return 0;
        !           994: }
        !           995:
        !           996: /*
        !           997:  * Establish I_T_L or I_T_L_Q nexus for new or existing command including
        !           998:  * ARBITRATION, SELECTION, and initial message out for IDENTIFY and queue
        !           999:  * messages.  Return -1 if selection could not execute for some reason, 0 if
        !          1000:  * selection succeded or failed because the target did not respond.
        !          1001:  */
        !          1002: int
        !          1003: sea_select(struct sea_softc *sea, struct sea_scb *scb)
        !          1004: {
        !          1005:        u_char msg[3], phase;
        !          1006:        u_char *data;
        !          1007:        int len;
        !          1008:        int timeout;
        !          1009:
        !          1010:        CONTROL = BASE_CMD;
        !          1011:        DATA = sea->our_id_mask;
        !          1012:        CONTROL = (BASE_CMD & ~CMD_INTR) | CMD_START_ARB;
        !          1013:
        !          1014:        /* wait for arbitration to complete */
        !          1015:        for (timeout = 0; timeout < 3000000L; timeout++)
        !          1016:                if (STATUS & STAT_ARB_CMPL)
        !          1017:                        break;
        !          1018:        if (!(STATUS & STAT_ARB_CMPL)) {
        !          1019:                if (STATUS & STAT_SEL) {
        !          1020:                        printf("%s: arbitration lost\n", sea->sc_dev.dv_xname);
        !          1021:                        scb->flags |= SCB_ERROR;
        !          1022:                } else {
        !          1023:                        printf("%s: arbitration timeout\n",
        !          1024:                            sea->sc_dev.dv_xname);
        !          1025:                        scb->flags |= SCB_TIMEOUT;
        !          1026:                }
        !          1027:                CONTROL = BASE_CMD;
        !          1028:                return -1;
        !          1029:        }
        !          1030:
        !          1031:        delay(2);
        !          1032:        DATA = (u_char)((1 << scb->xs->sc_link->target) | sea->our_id_mask);
        !          1033:        CONTROL =
        !          1034: #ifdef SEA_NOMSGS
        !          1035:            (BASE_CMD & ~CMD_INTR) | CMD_DRVR_ENABLE | CMD_SEL;
        !          1036: #else
        !          1037:            (BASE_CMD & ~CMD_INTR) | CMD_DRVR_ENABLE | CMD_SEL | CMD_ATTN;
        !          1038: #endif
        !          1039:        delay(1);
        !          1040:
        !          1041:        /* wait for a bsy from target */
        !          1042:        for (timeout = 0; timeout < 2000000L; timeout++)
        !          1043:                if (STATUS & STAT_BSY)
        !          1044:                        break;
        !          1045:        if (!(STATUS & STAT_BSY)) {
        !          1046:                /* should return some error to the higher level driver */
        !          1047:                CONTROL = BASE_CMD;
        !          1048:                scb->flags |= SCB_TIMEOUT;
        !          1049:                return 0;
        !          1050:        }
        !          1051:
        !          1052:        /* Try to make the target to take a message from us */
        !          1053: #ifdef SEA_NOMSGS
        !          1054:        CONTROL = (BASE_CMD & ~CMD_INTR) | CMD_DRVR_ENABLE;
        !          1055: #else
        !          1056:        CONTROL = (BASE_CMD & ~CMD_INTR) | CMD_DRVR_ENABLE | CMD_ATTN;
        !          1057: #endif
        !          1058:        delay(1);
        !          1059:
        !          1060:        /* should start a msg_out phase */
        !          1061:        for (timeout = 0; timeout < 2000000L; timeout++)
        !          1062:                if (STATUS & STAT_REQ)
        !          1063:                        break;
        !          1064:        /* Remove ATN. */
        !          1065:        CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
        !          1066:        if (!(STATUS & STAT_REQ)) {
        !          1067:                /*
        !          1068:                 * This should not be taken as an error, but more like an
        !          1069:                 * unsupported feature!  Should set a flag indicating that the
        !          1070:                 * target don't support messages, and continue without failure.
        !          1071:                 * (THIS IS NOT AN ERROR!)
        !          1072:                 */
        !          1073:        } else {
        !          1074:                msg[0] = MSG_IDENTIFY(scb->xs->sc_link->lun, 1);
        !          1075:                len = 1;
        !          1076:                data = msg;
        !          1077:                phase = PH_MSGOUT;
        !          1078:                /* Should do test on result of sea_transfer_pio(). */
        !          1079:                sea_transfer_pio(sea, &phase, &len, &data);
        !          1080:        }
        !          1081:        if (!(STATUS & STAT_BSY))
        !          1082:                printf("%s: after successful arbitrate: no STAT_BSY!\n",
        !          1083:                    sea->sc_dev.dv_xname);
        !          1084:
        !          1085:        sea->nexus = scb;
        !          1086:        sea->busy[scb->xs->sc_link->target] |= 1 << scb->xs->sc_link->lun;
        !          1087:        /* This assignment should depend on possibility to send a message to target. */
        !          1088:        CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
        !          1089:        /* XXX Reset pointer in command? */
        !          1090:        return 0;
        !          1091: }
        !          1092:
        !          1093: /*
        !          1094:  * Send an abort to the target.  Return 1 success, 0 on failure.
        !          1095:  */
        !          1096: int
        !          1097: sea_abort(struct sea_softc *sea, struct sea_scb *scb)
        !          1098: {
        !          1099:        struct sea_scb *tmp;
        !          1100:        u_char msg, phase, *msgptr;
        !          1101:        int len;
        !          1102:
        !          1103:        /*
        !          1104:         * If the command hasn't been issued yet, we simply remove it from the
        !          1105:         * issue queue
        !          1106:         * XXX Could avoid this loop.
        !          1107:         */
        !          1108:        TAILQ_FOREACH(tmp, &sea->ready_list, chain)
        !          1109:                if (scb == tmp) {
        !          1110:                        TAILQ_REMOVE(&sea->ready_list, scb, chain);
        !          1111:                        /* XXX Set some type of error result for operation. */
        !          1112:                        return 1;
        !          1113:                }
        !          1114:
        !          1115:        /*
        !          1116:         * If any commands are connected, we're going to fail the abort and let
        !          1117:         * the high level SCSI driver retry at a later time or issue a reset.
        !          1118:         */
        !          1119:        if (sea->nexus)
        !          1120:                return 0;
        !          1121:
        !          1122:        /*
        !          1123:         * If the command is currently disconnected from the bus, and there are
        !          1124:         * no connected commands, we reconnect the I_T_L or I_T_L_Q nexus
        !          1125:         * associated with it, go into message out, and send an abort message.
        !          1126:         */
        !          1127:        TAILQ_FOREACH(tmp, &sea->nexus_list, chain)
        !          1128:                if (scb == tmp) {
        !          1129:                        if (sea_select(sea, scb))
        !          1130:                                return 0;
        !          1131:
        !          1132:                        msg = MSG_ABORT;
        !          1133:                        msgptr = &msg;
        !          1134:                        len = 1;
        !          1135:                        phase = PH_MSGOUT;
        !          1136:                        CONTROL = BASE_CMD | CMD_ATTN;
        !          1137:                        sea_transfer_pio(sea, &phase, &len, &msgptr);
        !          1138:
        !          1139:                        TAILQ_FOREACH(tmp, &sea->nexus_list, chain)
        !          1140:                                if (scb == tmp) {
        !          1141:                                        TAILQ_REMOVE(&sea->nexus_list,
        !          1142:                                            scb, chain);
        !          1143:                                        /* XXX Set some type of error result
        !          1144:                                           for the operation. */
        !          1145:                                        return 1;
        !          1146:                                }
        !          1147:                }
        !          1148:
        !          1149:        /* Command not found in any queue; race condition? */
        !          1150:        return 1;
        !          1151: }
        !          1152:
        !          1153: void
        !          1154: sea_done(struct sea_softc *sea, struct sea_scb *scb)
        !          1155: {
        !          1156:        struct scsi_xfer *xs = scb->xs;
        !          1157:
        !          1158:        timeout_del(&scb->xs->stimeout);
        !          1159:
        !          1160:        xs->resid = scb->datalen;
        !          1161:
        !          1162:        /* XXXX need to get status */
        !          1163:        if (scb->flags == SCB_ACTIVE) {
        !          1164:                xs->resid = 0;
        !          1165:        } else {
        !          1166:                if (scb->flags & (SCB_TIMEOUT | SCB_ABORTED))
        !          1167:                        xs->error = XS_TIMEOUT;
        !          1168:                if (scb->flags & SCB_ERROR)
        !          1169:                        xs->error = XS_DRIVER_STUFFUP;
        !          1170:        }
        !          1171:        xs->flags |= ITSDONE;
        !          1172:        sea_free_scb(sea, scb, xs->flags);
        !          1173:        scsi_done(xs);
        !          1174: }
        !          1175:
        !          1176: /*
        !          1177:  * Wait for completion of command in polled mode.
        !          1178:  */
        !          1179: int
        !          1180: sea_poll(struct sea_softc *sea, struct scsi_xfer *xs, int count)
        !          1181: {
        !          1182:        int s;
        !          1183:
        !          1184:        while (count) {
        !          1185:                /* try to do something */
        !          1186:                s = splbio();
        !          1187:                if (!main_running)
        !          1188:                        sea_main();
        !          1189:                splx(s);
        !          1190:                if (xs->flags & ITSDONE)
        !          1191:                        return 0;
        !          1192:                delay(1000);
        !          1193:                count--;
        !          1194:        }
        !          1195:        return 1;
        !          1196: }
        !          1197:
        !          1198: /*
        !          1199:  * Do the transfer.  We know we are connected.  Update the flags, and call
        !          1200:  * sea_done() when task accomplished.  Dialog controlled by the target.
        !          1201:  */
        !          1202: void
        !          1203: sea_information_transfer(struct sea_softc *sea)
        !          1204: {
        !          1205:        int timeout;
        !          1206:        u_char msgout = MSG_NOOP;
        !          1207:        int len;
        !          1208:        int s;
        !          1209:        u_char *data;
        !          1210:        u_char phase, tmp, old_phase = PH_INVALID;
        !          1211:        struct sea_scb *scb = sea->nexus;
        !          1212:        int loop;
        !          1213:
        !          1214:        for (timeout = 0; timeout < 10000000L; timeout++) {
        !          1215:                tmp = STATUS;
        !          1216:                if (tmp & STAT_PARITY)
        !          1217:                        printf("%s: parity error detected\n",
        !          1218:                            sea->sc_dev.dv_xname);
        !          1219:                if (!(tmp & STAT_BSY)) {
        !          1220:                        for (loop = 0; loop < 20; loop++)
        !          1221:                                if ((tmp = STATUS) & STAT_BSY)
        !          1222:                                        break;
        !          1223:                        if (!(tmp & STAT_BSY)) {
        !          1224:                                printf("%s: !STAT_BSY unit in data transfer!\n",
        !          1225:                                    sea->sc_dev.dv_xname);
        !          1226:                                s = splbio();
        !          1227:                                sea->nexus = NULL;
        !          1228:                                scb->flags = SCB_ERROR;
        !          1229:                                splx(s);
        !          1230:                                sea_done(sea, scb);
        !          1231:                                return;
        !          1232:                        }
        !          1233:                }
        !          1234:
        !          1235:                /* we only have a valid SCSI phase when REQ is asserted */
        !          1236:                if (!(tmp & STAT_REQ))
        !          1237:                        continue;
        !          1238:
        !          1239:                if (sea->type == FDOMAIN840)
        !          1240:                        tmp = ((tmp & 0x08) >> 2) |
        !          1241:                              ((tmp & 0x02) << 2) |
        !          1242:                               (tmp & 0xf5);
        !          1243:                phase = tmp & PH_MASK;
        !          1244:                if (phase != old_phase)
        !          1245:                        old_phase = phase;
        !          1246:
        !          1247:                switch (phase) {
        !          1248:                case PH_DATAOUT:
        !          1249: #ifdef SEA_NODATAOUT
        !          1250:                        printf("%s: SEA_NODATAOUT set, attempted DATAOUT aborted\n",
        !          1251:                            sea->sc_dev.dv_xname);
        !          1252:                        msgout = MSG_ABORT;
        !          1253:                        CONTROL = BASE_CMD | CMD_ATTN;
        !          1254:                        break;
        !          1255: #endif
        !          1256:                case PH_DATAIN:
        !          1257:                        if (!scb->data)
        !          1258:                                printf("no data address!\n");
        !          1259: #ifdef SEA_BLINDTRANSFER
        !          1260:                        if (scb->datalen && !(scb->datalen % BLOCK_SIZE)) {
        !          1261:                                while (scb->datalen) {
        !          1262:                                        for (loop = 0; loop < 50000; loop++)
        !          1263:                                                if ((tmp = STATUS) & STAT_REQ)
        !          1264:                                                        break;
        !          1265:                                        if (!(tmp & STAT_REQ)) {
        !          1266:                                                printf("%s: timeout waiting for STAT_REQ\n",
        !          1267:                                                    sea->sc_dev.dv_xname);
        !          1268:                                                /* XXX Do something? */
        !          1269:                                        }
        !          1270:                                        if (sea->type == FDOMAIN840)
        !          1271:                                                tmp = ((tmp & 0x08) >> 2) |
        !          1272:                                                      ((tmp & 0x02) << 2) |
        !          1273:                                                       (tmp & 0xf5);
        !          1274:                                        if ((tmp & PH_MASK) != phase)
        !          1275:                                                break;
        !          1276:                                        if (!(phase & STAT_IO)) {
        !          1277:                                                int block = BLOCK_SIZE;
        !          1278:                                                void *a = sea->maddr_dr;
        !          1279: #ifdef SEA_ASSEMBLER
        !          1280:                                                asm("shr $2, %%ecx\n\t\
        !          1281:                                                    cld\n\t\
        !          1282:                                                    rep\n\t\
        !          1283:                                                    movsl" :
        !          1284:                                                    "=S" (scb->data),
        !          1285:                                                        "=c" (block) ,
        !          1286:                                                    "=D" (a) :
        !          1287:                                                    "0" (scb->data),
        !          1288:                                                    "2" (a),
        !          1289:                                                    "1" (block) );
        !          1290: #else
        !          1291:                                                for (count = 0;
        !          1292:                                                    count < BLOCK_SIZE;
        !          1293:                                                    count++)
        !          1294:                                                        DATA = *(scb->data++);
        !          1295: #endif
        !          1296:                                        } else {
        !          1297:                                                int block = BLOCK_SIZE;
        !          1298:                                                void *a = sea->maddr_dr;
        !          1299: #ifdef SEA_ASSEMBLER
        !          1300:                                                asm("shr $2, %%ecx\n\t\
        !          1301:                                                    cld\n\t\
        !          1302:                                                    rep\n\t\
        !          1303:                                                    movsl" :
        !          1304:                                                    "=D" (scb->data), "=c" (block) ,
        !          1305:                                                    "=S" (a) :
        !          1306:                                                    "0" (scb->data),
        !          1307:                                                        "2" (a) ,
        !          1308:                                                    "1" (block) );
        !          1309: #else
        !          1310:                                                for (count = 0;
        !          1311:                                                    count < BLOCK_SIZE;
        !          1312:                                                    count++)
        !          1313:                                                        *(scb->data++) = DATA;
        !          1314: #endif
        !          1315:                                        }
        !          1316:                                        scb->datalen -= BLOCK_SIZE;
        !          1317:                                }
        !          1318:                        }
        !          1319: #endif
        !          1320:                        if (scb->datalen)
        !          1321:                                sea_transfer_pio(sea, &phase, &scb->datalen,
        !          1322:                                    &scb->data);
        !          1323:                        break;
        !          1324:                case PH_MSGIN:
        !          1325:                        /* Multibyte messages should not be present here. */
        !          1326:                        len = 1;
        !          1327:                        data = &tmp;
        !          1328:                        sea_transfer_pio(sea, &phase, &len, &data);
        !          1329:                        /* scb->MessageIn = tmp; */
        !          1330:
        !          1331:                        switch (tmp) {
        !          1332:                        case MSG_ABORT:
        !          1333:                                scb->flags = SCB_ABORTED;
        !          1334:                                printf("sea: command aborted by target\n");
        !          1335:                                CONTROL = BASE_CMD;
        !          1336:                                sea_done(sea, scb);
        !          1337:                                return;
        !          1338:                        case MSG_CMDCOMPLETE:
        !          1339:                                s = splbio();
        !          1340:                                sea->nexus = NULL;
        !          1341:                                splx(s);
        !          1342:                                sea->busy[scb->xs->sc_link->target] &=
        !          1343:                                    ~(1 << scb->xs->sc_link->lun);
        !          1344:                                CONTROL = BASE_CMD;
        !          1345:                                sea_done(sea, scb);
        !          1346:                                return;
        !          1347:                        case MSG_MESSAGE_REJECT:
        !          1348:                                printf("%s: message_reject received\n",
        !          1349:                                    sea->sc_dev.dv_xname);
        !          1350:                                break;
        !          1351:                        case MSG_DISCONNECT:
        !          1352:                                s = splbio();
        !          1353:                                TAILQ_INSERT_TAIL(&sea->nexus_list,
        !          1354:                                    scb, chain);
        !          1355:                                sea->nexus = NULL;
        !          1356:                                CONTROL = BASE_CMD;
        !          1357:                                splx(s);
        !          1358:                                return;
        !          1359:                        case MSG_SAVEDATAPOINTER:
        !          1360:                        case MSG_RESTOREPOINTERS:
        !          1361:                                /* save/restore of pointers are ignored */
        !          1362:                                break;
        !          1363:                        default:
        !          1364:                                /*
        !          1365:                                 * This should be handled in the pio data
        !          1366:                                 * transfer phase, as the ATN should be raised
        !          1367:                                 * before ACK goes false when rejecting a
        !          1368:                                 * message.
        !          1369:                                 */
        !          1370:                                printf("%s: unknown message in: %x\n",
        !          1371:                                    sea->sc_dev.dv_xname, tmp);
        !          1372:                                break;
        !          1373:                        } /* switch (tmp) */
        !          1374:                        break;
        !          1375:                case PH_MSGOUT:
        !          1376:                        len = 1;
        !          1377:                        data = &msgout;
        !          1378:                        /* sea->last_message = msgout; */
        !          1379:                        sea_transfer_pio(sea, &phase, &len, &data);
        !          1380:                        if (msgout == MSG_ABORT) {
        !          1381:                                printf("%s: sent message abort to target\n",
        !          1382:                                    sea->sc_dev.dv_xname);
        !          1383:                                s = splbio();
        !          1384:                                sea->busy[scb->xs->sc_link->target] &=
        !          1385:                                    ~(1 << scb->xs->sc_link->lun);
        !          1386:                                sea->nexus = NULL;
        !          1387:                                scb->flags = SCB_ABORTED;
        !          1388:                                splx(s);
        !          1389:                                /* enable interrupt from scsi */
        !          1390:                                sea_done(sea, scb);
        !          1391:                                return;
        !          1392:                        }
        !          1393:                        msgout = MSG_NOOP;
        !          1394:                        break;
        !          1395:                case PH_CMD:
        !          1396:                        len = scb->xs->cmdlen;
        !          1397:                        data = (char *) scb->xs->cmd;
        !          1398:                        sea_transfer_pio(sea, &phase, &len, &data);
        !          1399:                        break;
        !          1400:                case PH_STAT:
        !          1401:                        len = 1;
        !          1402:                        data = &tmp;
        !          1403:                        sea_transfer_pio(sea, &phase, &len, &data);
        !          1404:                        scb->xs->status = tmp;
        !          1405:                        break;
        !          1406:                default:
        !          1407:                        printf("sea: unknown phase\n");
        !          1408:                } /* switch (phase) */
        !          1409:        } /* for (...) */
        !          1410:
        !          1411:        /* If we get here we have got a timeout! */
        !          1412:        printf("%s: timeout in data transfer\n", sea->sc_dev.dv_xname);
        !          1413:        scb->flags = SCB_TIMEOUT;
        !          1414:        /* XXX Should I clear scsi-bus state? */
        !          1415:        sea_done(sea, scb);
        !          1416: }

CVSweb