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