Annotation of sys/dev/ic/trm.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: trm.c,v 1.7 2005/12/03 16:53:16 krw Exp $
! 2: * ------------------------------------------------------------
! 3: * O.S : OpenBSD
! 4: * File Name : trm.c
! 5: * Device Driver for Tekram DC395U/UW/F,DC315/U
! 6: * PCI SCSI Bus Master Host Adapter
! 7: * (SCSI chip set used Tekram ASIC TRM-S1040)
! 8: *
! 9: * (C)Copyright 1995-1999 Tekram Technology Co., Ltd.
! 10: * (C)Copyright 2001-2002 Ashley R. Martens and Kenneth R Westerback
! 11: * ------------------------------------------------------------
! 12: * HISTORY:
! 13: *
! 14: * REV# DATE NAME DESCRIPTION
! 15: * 1.00 05/01/99 ERICH CHEN First released for NetBSD 1.4.x
! 16: * 1.01 00/00/00 MARTIN AKESSON Port to OpenBSD 2.8
! 17: * 1.02 09/19/01 ASHLEY MARTENS Cleanup and formatting
! 18: * 2.00 01/00/02 KENNETH R WESTERBACK Rewrite of the bus and code logic
! 19: * ------------------------------------------------------------
! 20: *
! 21: * Redistribution and use in source and binary forms, with or without
! 22: * modification, are permitted provided that the following conditions
! 23: * are met:
! 24: * 1. Redistributions of source code must retain the above copyright
! 25: * notice, this list of conditions and the following disclaimer.
! 26: * 2. Redistributions in binary form must reproduce the above copyright
! 27: * notice, this list of conditions and the following disclaimer in the
! 28: * documentation and/or other materials provided with the distribution.
! 29: * 3. The name of the author may not be used to endorse or promote products
! 30: * derived from this software without specific prior written permission.
! 31: *
! 32: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 33: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 34: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 35: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 36: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 37: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 38: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 39: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 40: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 41: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 42: *
! 43: * ------------------------------------------------------------
! 44: */
! 45:
! 46: #include <sys/param.h>
! 47: #include <sys/systm.h>
! 48: #include <sys/kernel.h>
! 49: #include <sys/malloc.h>
! 50: #include <sys/buf.h>
! 51: #include <sys/device.h>
! 52:
! 53: #include <machine/bus.h>
! 54:
! 55: #include <scsi/scsi_all.h>
! 56: #include <scsi/scsiconf.h>
! 57: #include <scsi/scsi_message.h>
! 58:
! 59: #include <dev/pci/pcidevs.h>
! 60: #include <dev/ic/trm.h>
! 61:
! 62: /* #define TRM_DEBUG0 */
! 63:
! 64: void trm_minphys(struct buf *);
! 65:
! 66: void trm_initSRB(struct trm_scsi_req_q *);
! 67:
! 68: void trm_check_eeprom(struct trm_adapter_nvram *, bus_space_tag_t, bus_space_handle_t);
! 69: void trm_read_all (struct trm_adapter_nvram *, bus_space_tag_t, bus_space_handle_t);
! 70: void trm_write_all (struct trm_adapter_nvram *, bus_space_tag_t, bus_space_handle_t);
! 71:
! 72: void trm_set_data (bus_space_tag_t, bus_space_handle_t, u_int8_t, u_int8_t);
! 73: void trm_write_cmd(bus_space_tag_t, bus_space_handle_t, u_int8_t, u_int8_t);
! 74:
! 75: u_int8_t trm_get_data(bus_space_tag_t, bus_space_handle_t, u_int8_t);
! 76:
! 77: void trm_wait_30us(bus_space_tag_t, bus_space_handle_t);
! 78:
! 79: int trm_scsi_cmd(struct scsi_xfer *);
! 80:
! 81: struct trm_scsi_req_q *trm_GetFreeSRB(struct trm_softc *);
! 82:
! 83: void trm_DataOutPhase0(struct trm_softc *, struct trm_scsi_req_q *, u_int8_t *);
! 84: void trm_DataInPhase0 (struct trm_softc *, struct trm_scsi_req_q *, u_int8_t *);
! 85: void trm_StatusPhase0 (struct trm_softc *, struct trm_scsi_req_q *, u_int8_t *);
! 86: void trm_MsgOutPhase0 (struct trm_softc *, struct trm_scsi_req_q *, u_int8_t *);
! 87: void trm_MsgInPhase0 (struct trm_softc *, struct trm_scsi_req_q *, u_int8_t *);
! 88: void trm_DataOutPhase1(struct trm_softc *, struct trm_scsi_req_q *, u_int8_t *);
! 89: void trm_DataInPhase1 (struct trm_softc *, struct trm_scsi_req_q *, u_int8_t *);
! 90: void trm_CommandPhase1(struct trm_softc *, struct trm_scsi_req_q *, u_int8_t *);
! 91: void trm_StatusPhase1 (struct trm_softc *, struct trm_scsi_req_q *, u_int8_t *);
! 92: void trm_MsgOutPhase1 (struct trm_softc *, struct trm_scsi_req_q *, u_int8_t *);
! 93: void trm_MsgInPhase1 (struct trm_softc *, struct trm_scsi_req_q *, u_int8_t *);
! 94: void trm_Nop (struct trm_softc *, struct trm_scsi_req_q *, u_int8_t *);
! 95:
! 96: void trm_SetXferParams (struct trm_softc *, struct trm_dcb *, int);
! 97:
! 98: void trm_DataIO_transfer(struct trm_softc *, struct trm_scsi_req_q *, u_int16_t);
! 99:
! 100: int trm_StartSRB (struct trm_softc *, struct trm_scsi_req_q *);
! 101: void trm_ReleaseSRB (struct trm_softc *, struct trm_scsi_req_q *);
! 102: void trm_RewaitSRB (struct trm_softc *, struct trm_scsi_req_q *);
! 103: void trm_FinishSRB (struct trm_softc *, struct trm_scsi_req_q *);
! 104: void trm_RequestSense(struct trm_softc *, struct trm_scsi_req_q *);
! 105:
! 106: void trm_initAdapter (struct trm_softc *);
! 107: void trm_Disconnect (struct trm_softc *);
! 108: void trm_Reselect (struct trm_softc *);
! 109: void trm_GoingSRB_Done (struct trm_softc *);
! 110: void trm_ScsiRstDetect (struct trm_softc *);
! 111: void trm_ResetSCSIBus (struct trm_softc *);
! 112: void trm_reset (struct trm_softc *);
! 113: void trm_StartWaitingSRB (struct trm_softc *);
! 114: void trm_ResetAllDevParam(struct trm_softc *);
! 115: void trm_RecoverSRB (struct trm_softc *);
! 116: void trm_linkSRB (struct trm_softc *);
! 117:
! 118: void trm_initACB(struct trm_softc *, int);
! 119:
! 120: void trm_ResetDevParam(struct trm_softc *, struct trm_dcb *, u_int8_t);
! 121:
! 122: void trm_EnableMsgOut(struct trm_softc *, u_int8_t);
! 123:
! 124: void trm_timeout(void *);
! 125:
! 126: void trm_print_info(struct trm_softc *, struct trm_dcb *);
! 127:
! 128: /*
! 129: * Define structures
! 130: */
! 131: struct cfdriver trm_cd = {
! 132: NULL, "trm", DV_DULL
! 133: };
! 134:
! 135: struct scsi_adapter trm_switch = {
! 136: trm_scsi_cmd,
! 137: trm_minphys,
! 138: NULL,
! 139: NULL
! 140: };
! 141:
! 142: static struct scsi_device trm_device = {
! 143: NULL, /* Use default error handler */
! 144: NULL, /* have a queue, served by this */
! 145: NULL, /* have no async handler */
! 146: NULL, /* Use default 'done' routine */
! 147: };
! 148:
! 149: /*
! 150: * ------------------------------------------------------------
! 151: *
! 152: * stateV = (void *) trm_SCSI_phase0[phase]
! 153: *
! 154: * ------------------------------------------------------------
! 155: */
! 156: static void *trm_SCSI_phase0[8] = {
! 157: trm_DataOutPhase0, /* phase:0 */
! 158: trm_DataInPhase0, /* phase:1 */
! 159: trm_Nop, /* phase:2 */
! 160: trm_StatusPhase0, /* phase:3 */
! 161: trm_Nop, /* phase:4 */
! 162: trm_Nop, /* phase:5 */
! 163: trm_MsgOutPhase0, /* phase:6 */
! 164: trm_MsgInPhase0, /* phase:7 */
! 165: };
! 166:
! 167: /*
! 168: * ------------------------------------------------------------
! 169: *
! 170: * stateV = (void *) trm_SCSI_phase1[phase]
! 171: *
! 172: * ------------------------------------------------------------
! 173: */
! 174: static void *trm_SCSI_phase1[8] = {
! 175: trm_DataOutPhase1, /* phase:0 */
! 176: trm_DataInPhase1, /* phase:1 */
! 177: trm_CommandPhase1, /* phase:2 */
! 178: trm_StatusPhase1, /* phase:3 */
! 179: trm_Nop, /* phase:4 */
! 180: trm_Nop, /* phase:5 */
! 181: trm_MsgOutPhase1, /* phase:6 */
! 182: trm_MsgInPhase1, /* phase:7 */
! 183: };
! 184:
! 185:
! 186: struct trm_adapter_nvram trm_eepromBuf[TRM_MAX_ADAPTER_NUM];
! 187: /*
! 188: *Fast20: 000 50ns, 20.0 Mbytes/s
! 189: * 001 75ns, 13.3 Mbytes/s
! 190: * 010 100ns, 10.0 Mbytes/s
! 191: * 011 125ns, 8.0 Mbytes/s
! 192: * 100 150ns, 6.6 Mbytes/s
! 193: * 101 175ns, 5.7 Mbytes/s
! 194: * 110 200ns, 5.0 Mbytes/s
! 195: * 111 250ns, 4.0 Mbytes/s
! 196: *
! 197: *Fast40: 000 25ns, 40.0 Mbytes/s
! 198: * 001 50ns, 20.0 Mbytes/s
! 199: * 010 75ns, 13.3 Mbytes/s
! 200: * 011 100ns, 10.0 Mbytes/s
! 201: * 100 125ns, 8.0 Mbytes/s
! 202: * 101 150ns, 6.6 Mbytes/s
! 203: * 110 175ns, 5.7 Mbytes/s
! 204: * 111 200ns, 5.0 Mbytes/s
! 205: */
! 206:
! 207: /*
! 208: * real period:
! 209: */
! 210: u_int8_t trm_clock_period[8] = {
! 211: /* nanosecond divided by 4 */
! 212: 12, /* 48 ns 20 MB/sec */
! 213: 18, /* 72 ns 13.3 MB/sec */
! 214: 25, /* 100 ns 10.0 MB/sec */
! 215: 31, /* 124 ns 8.0 MB/sec */
! 216: 37, /* 148 ns 6.6 MB/sec */
! 217: 43, /* 172 ns 5.7 MB/sec */
! 218: 50, /* 200 ns 5.0 MB/sec */
! 219: 62 /* 248 ns 4.0 MB/sec */
! 220: };
! 221:
! 222: /*
! 223: * ------------------------------------------------------------
! 224: * Function : trm_GetFreeSRB
! 225: * Purpose : Get the first free SRB
! 226: * Inputs :
! 227: * Return : NULL or a free SCSI Request block
! 228: * ------------------------------------------------------------
! 229: */
! 230: struct trm_scsi_req_q *
! 231: trm_GetFreeSRB(struct trm_softc *sc)
! 232: {
! 233: struct trm_scsi_req_q *pSRB;
! 234:
! 235: /* ASSUME we are called from inside a splbio()/splx() region */
! 236:
! 237: pSRB = TAILQ_FIRST(&sc->freeSRB);
! 238:
! 239: if (pSRB != NULL)
! 240: TAILQ_REMOVE(&sc->freeSRB, pSRB, link);
! 241:
! 242: #ifdef TRM_DEBUG0
! 243: printf("%s: trm_GetFreeSRB. pSRB = %p, next pSRB = %p\n",
! 244: sc->sc_device.dv_xname, pSRB, TAILQ_FIRST(&sc->freeSRB));
! 245: #endif
! 246:
! 247: return pSRB;
! 248: }
! 249:
! 250: /*
! 251: * ------------------------------------------------------------
! 252: * Function : trm_RewaitSRB
! 253: * Purpose : Q back to pending Q
! 254: * Inputs : struct trm_dcb * -
! 255: * struct trm_scsi_req_q * -
! 256: * ------------------------------------------------------------
! 257: */
! 258: void
! 259: trm_RewaitSRB(struct trm_softc *sc, struct trm_scsi_req_q *pSRB)
! 260: {
! 261: int intflag;
! 262:
! 263: intflag = splbio();
! 264:
! 265: if ((pSRB->SRBFlag & TRM_ON_WAITING_SRB) != 0) {
! 266: pSRB->SRBFlag &= ~TRM_ON_WAITING_SRB;
! 267: TAILQ_REMOVE(&sc->waitingSRB, pSRB, link);
! 268: }
! 269:
! 270: if ((pSRB->SRBFlag & TRM_ON_GOING_SRB) != 0) {
! 271: pSRB->SRBFlag &= ~TRM_ON_GOING_SRB;
! 272: TAILQ_REMOVE(&sc->goingSRB, pSRB, link);
! 273: }
! 274:
! 275: pSRB->SRBState = TRM_READY;
! 276: pSRB->TargetStatus = SCSI_OK;
! 277: pSRB->AdaptStatus = TRM_STATUS_GOOD;
! 278:
! 279: pSRB->SRBFlag |= TRM_ON_WAITING_SRB;
! 280: TAILQ_INSERT_HEAD(&sc->waitingSRB, pSRB, link);
! 281:
! 282: splx(intflag);
! 283: }
! 284:
! 285: /*
! 286: * ------------------------------------------------------------
! 287: * Function : trm_StartWaitingSRB
! 288: * Purpose : If there is no active DCB then run robin through
! 289: * the DCB's to find the next waiting SRB
! 290: * and move it to the going list.
! 291: * Inputs : struct trm_softc * -
! 292: * ------------------------------------------------------------
! 293: */
! 294: void
! 295: trm_StartWaitingSRB(struct trm_softc *sc)
! 296: {
! 297: struct trm_scsi_req_q *pSRB, *next;
! 298: int intflag;
! 299:
! 300: intflag = splbio();
! 301:
! 302: if ((sc->pActiveDCB != NULL) ||
! 303: (TAILQ_EMPTY(&sc->waitingSRB)) ||
! 304: (sc->sc_Flag & (RESET_DETECT | RESET_DONE | RESET_DEV)) != 0)
! 305: return;
! 306:
! 307: for (pSRB = TAILQ_FIRST(&sc->waitingSRB); pSRB != NULL; pSRB = next) {
! 308: next = TAILQ_NEXT(pSRB, link);
! 309: if (trm_StartSRB(sc, pSRB) == 0) {
! 310: pSRB->SRBFlag &= ~TRM_ON_WAITING_SRB;
! 311: TAILQ_REMOVE(&sc->waitingSRB, pSRB, link);
! 312: pSRB->SRBFlag |= TRM_ON_GOING_SRB;
! 313: TAILQ_INSERT_TAIL(&sc->goingSRB, pSRB, link);
! 314: break;
! 315: }
! 316: }
! 317:
! 318: splx(intflag);
! 319: }
! 320:
! 321: /*
! 322: * ------------------------------------------------------------
! 323: * Function : trm_scsi_cmd
! 324: * Purpose : enqueues a SCSI command
! 325: * Inputs :
! 326: * Call By : GENERIC SCSI driver
! 327: * ------------------------------------------------------------
! 328: */
! 329: int
! 330: trm_scsi_cmd(struct scsi_xfer *xs)
! 331: {
! 332: struct trm_scsi_req_q *pSRB;
! 333: bus_space_handle_t ioh;
! 334: struct trm_softc *sc;
! 335: bus_space_tag_t iot;
! 336: struct trm_dcb *pDCB;
! 337: u_int8_t target, lun;
! 338: int i, error, intflag, xferflags;
! 339:
! 340: target = xs->sc_link->target;
! 341: lun = xs->sc_link->lun;
! 342:
! 343: sc = (struct trm_softc *)xs->sc_link->adapter_softc;
! 344: ioh = sc->sc_iohandle;
! 345: iot = sc->sc_iotag;
! 346:
! 347: #ifdef TRM_DEBUG0
! 348: if ((xs->flags & SCSI_POLL) != 0)
! 349: printf("%s: trm_scsi_cmd. sc = %p, xs = %p, targ/lun = %d/%d opcode = 0x%02x\n",
! 350: sc->sc_device.dv_xname, sc, xs, target, lun, xs->cmd->opcode);
! 351: #endif
! 352:
! 353: if (target >= TRM_MAX_TARGETS) {
! 354: printf("%s: target=%d >= %d\n",
! 355: sc->sc_device.dv_xname, target, TRM_MAX_TARGETS);
! 356: xs->error = XS_DRIVER_STUFFUP;
! 357: return COMPLETE;
! 358: }
! 359: if (lun >= TRM_MAX_LUNS) {
! 360: printf("%s: lun=%d >= %d\n",
! 361: sc->sc_device.dv_xname, lun, TRM_MAX_LUNS);
! 362: xs->error = XS_DRIVER_STUFFUP;
! 363: return COMPLETE;
! 364: }
! 365:
! 366: pDCB = sc->pDCB[target][lun];
! 367: if (pDCB == NULL) {
! 368: /* Removed as a result of INQUIRY proving no device present */
! 369: xs->error = XS_DRIVER_STUFFUP;
! 370: return COMPLETE;
! 371: }
! 372:
! 373: xferflags = xs->flags;
! 374: if (xferflags & SCSI_RESET) {
! 375: #ifdef TRM_DEBUG0
! 376: printf("%s: trm_reset\n", sc->sc_device.dv_xname);
! 377: #endif
! 378: trm_reset(sc);
! 379: xs->error = XS_NOERROR;
! 380: return COMPLETE;
! 381: }
! 382:
! 383: if (xferflags & ITSDONE) {
! 384: #ifdef TRM_DEBUG0
! 385: printf("%s: Is it done?\n", sc->sc_device.dv_xname);
! 386: #endif
! 387: xs->flags &= ~ITSDONE;
! 388: }
! 389:
! 390: xs->error = XS_NOERROR;
! 391: xs->status = SCSI_OK;
! 392: xs->resid = 0;
! 393:
! 394: intflag = splbio();
! 395:
! 396: pSRB = trm_GetFreeSRB(sc);
! 397:
! 398: if (pSRB == NULL) {
! 399: splx(intflag);
! 400: return TRY_AGAIN_LATER;
! 401: }
! 402:
! 403: /*
! 404: * BuildSRB(pSRB,pDCB);
! 405: */
! 406: if (xs->datalen != 0) {
! 407: #ifdef TRM_DEBUG0
! 408: printf("%s: xs->datalen=%x\n", sc->sc_device.dv_xname,
! 409: (u_int32_t)xs->datalen);
! 410: printf("%s: sc->sc_dmatag=0x%x\n", sc->sc_device.dv_xname,
! 411: (u_int32_t)sc->sc_dmatag);
! 412: printf("%s: pSRB->dmamapxfer=0x%x\n", sc->sc_device.dv_xname,
! 413: (u_int32_t)pSRB->dmamapxfer);
! 414: printf("%s: xs->data=0x%x\n", sc->sc_device.dv_xname,
! 415: (u_int32_t)xs->data);
! 416: #endif
! 417: if ((error = bus_dmamap_load(sc->sc_dmatag, pSRB->dmamapxfer,
! 418: xs->data, xs->datalen, NULL,
! 419: (xferflags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
! 420: BUS_DMA_WAITOK)) != 0) {
! 421: printf("%s: DMA transfer map unable to load, error = %d\n"
! 422: , sc->sc_device.dv_xname, error);
! 423: xs->error = XS_DRIVER_STUFFUP;
! 424: /*
! 425: * free SRB
! 426: */
! 427: TAILQ_INSERT_HEAD(&sc->freeSRB, pSRB, link);
! 428: splx(intflag);
! 429: return COMPLETE;
! 430: }
! 431:
! 432: bus_dmamap_sync(sc->sc_dmatag, pSRB->dmamapxfer,
! 433: 0, pSRB->dmamapxfer->dm_mapsize,
! 434: (xferflags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
! 435:
! 436: /*
! 437: * Set up the scatter gather list
! 438: */
! 439: for (i = 0; i < pSRB->dmamapxfer->dm_nsegs; i++) {
! 440: pSRB->SegmentX[i].address = pSRB->dmamapxfer->dm_segs[i].ds_addr;
! 441: pSRB->SegmentX[i].length = pSRB->dmamapxfer->dm_segs[i].ds_len;
! 442: }
! 443: pSRB->SRBTotalXferLength = xs->datalen;
! 444: pSRB->SRBSGCount = pSRB->dmamapxfer->dm_nsegs;
! 445: }
! 446:
! 447: pSRB->pSRBDCB = pDCB;
! 448: pSRB->xs = xs;
! 449: pSRB->ScsiCmdLen = xs->cmdlen;
! 450:
! 451: memcpy(pSRB->CmdBlock, xs->cmd, xs->cmdlen);
! 452:
! 453: splx (intflag);
! 454:
! 455: timeout_set(&xs->stimeout, trm_timeout, pSRB);
! 456:
! 457: intflag = splbio();
! 458:
! 459: pSRB->SRBFlag |= TRM_ON_WAITING_SRB;
! 460: TAILQ_INSERT_TAIL(&sc->waitingSRB, pSRB, link);
! 461: trm_StartWaitingSRB(sc);
! 462:
! 463: if ((xferflags & SCSI_POLL) == 0) {
! 464: timeout_add(&xs->stimeout, (xs->timeout * hz) / 1000);
! 465: splx(intflag);
! 466: return SUCCESSFULLY_QUEUED;
! 467: }
! 468:
! 469: while ((--xs->timeout > 0) && ((xs->flags & ITSDONE) == 0)) {
! 470: trm_Interrupt(sc);
! 471: DELAY(1000);
! 472: }
! 473:
! 474: if (xs->timeout == 0)
! 475: trm_timeout(pSRB);
! 476:
! 477: splx(intflag);
! 478: return COMPLETE;
! 479: }
! 480:
! 481: /*
! 482: * ------------------------------------------------------------
! 483: * Function : trm_ResetAllDevParam
! 484: * Purpose :
! 485: * Inputs : struct trm_softc *
! 486: * ------------------------------------------------------------
! 487: */
! 488: void
! 489: trm_ResetAllDevParam(struct trm_softc *sc)
! 490: {
! 491: struct trm_adapter_nvram *pEEpromBuf;
! 492: int target, quirks;
! 493:
! 494: pEEpromBuf = &trm_eepromBuf[sc->sc_AdapterUnit];
! 495:
! 496: for (target = 0; target < TRM_MAX_TARGETS; target++) {
! 497: if (target == sc->sc_AdaptSCSIID)
! 498: continue;
! 499:
! 500: if ((sc->pDCB[target][0]->DCBFlag & TRM_QUIRKS_VALID) == 0)
! 501: quirks = SDEV_NOWIDE | SDEV_NOSYNC | SDEV_NOTAGS;
! 502: else
! 503: quirks = sc->pDCB[target][0]->sc_link->quirks;
! 504:
! 505: trm_ResetDevParam(sc, sc->pDCB[target][0], quirks);
! 506: }
! 507: }
! 508:
! 509: /*
! 510: * ------------------------------------------------------------
! 511: * Function : trm_ResetDevParam
! 512: * Purpose :
! 513: * Inputs :
! 514: * ------------------------------------------------------------
! 515: */
! 516: void
! 517: trm_ResetDevParam(struct trm_softc *sc, struct trm_dcb *pDCB, u_int8_t quirks)
! 518: {
! 519: struct trm_adapter_nvram *pEEpromBuf = &trm_eepromBuf[sc->sc_AdapterUnit];
! 520: u_int8_t PeriodIndex;
! 521: const int target = pDCB->target;
! 522:
! 523: pDCB->DCBFlag &= TRM_QUIRKS_VALID;
! 524: pDCB->DCBFlag |= (TRM_WIDE_NEGO_ENABLE | TRM_SYNC_NEGO_ENABLE);
! 525:
! 526: pDCB->SyncPeriod = 0;
! 527: pDCB->SyncOffset = 0;
! 528: pDCB->MaxNegoPeriod = 0;
! 529:
! 530: pDCB->DevMode = pEEpromBuf->NvramTarget[target].NvmTarCfg0;
! 531:
! 532: pDCB->IdentifyMsg = MSG_IDENTIFY(pDCB->lun, ((pDCB->DevMode & TRM_DISCONNECT) != 0));
! 533:
! 534: if (((quirks & SDEV_NOWIDE) == 0) &&
! 535: (pDCB->DevMode & TRM_WIDE) &&
! 536: ((sc->sc_config & HCC_WIDE_CARD) != 0))
! 537: pDCB->DCBFlag |= TRM_WIDE_NEGO_16BIT;
! 538:
! 539: if (((quirks & SDEV_NOSYNC) == 0) &&
! 540: ((pDCB->DevMode & TRM_SYNC) != 0)) {
! 541: PeriodIndex = pEEpromBuf->NvramTarget[target].NvmTarPeriod & 0x07;
! 542: pDCB->MaxNegoPeriod = trm_clock_period[PeriodIndex];
! 543: }
! 544:
! 545: if (((quirks & SDEV_NOTAGS) == 0) &&
! 546: ((pDCB->DevMode & TRM_TAG_QUEUING) != 0) &&
! 547: ((pDCB->DevMode & TRM_DISCONNECT) != 0))
! 548: /* TODO XXXX: Every device(lun) gets to queue TagMaxNum commands? */
! 549: pDCB->DCBFlag |= TRM_USE_TAG_QUEUING;
! 550:
! 551: trm_SetXferParams(sc, pDCB, 0);
! 552: }
! 553:
! 554: /*
! 555: * ------------------------------------------------------------
! 556: * Function : trm_RecoverSRB
! 557: * Purpose : Moves all SRBs from Going to Waiting for all the Link DCBs
! 558: * Inputs : struct trm_softc * -
! 559: * ------------------------------------------------------------
! 560: */
! 561: void
! 562: trm_RecoverSRB(struct trm_softc *sc)
! 563: {
! 564: struct trm_scsi_req_q *pSRB;
! 565:
! 566: /* ASSUME we are inside splbio()/splx() */
! 567:
! 568: while ((pSRB = TAILQ_FIRST(&sc->goingSRB)) != NULL) {
! 569: pSRB->SRBFlag &= ~TRM_ON_GOING_SRB;
! 570: TAILQ_REMOVE(&sc->goingSRB, pSRB, link);
! 571: pSRB->SRBFlag |= TRM_ON_WAITING_SRB;
! 572: TAILQ_INSERT_HEAD(&sc->waitingSRB, pSRB, link);
! 573: }
! 574: }
! 575:
! 576: /*
! 577: * ------------------------------------------------------------
! 578: * Function : trm_reset
! 579: * Purpose : perform a hard reset on the SCSI bus (and TRM_S1040 chip).
! 580: * Inputs :
! 581: * ------------------------------------------------------------
! 582: */
! 583: void
! 584: trm_reset (struct trm_softc *sc)
! 585: {
! 586: const bus_space_handle_t ioh = sc->sc_iohandle;
! 587: const bus_space_tag_t iot = sc->sc_iotag;
! 588: int i, intflag;
! 589:
! 590: #ifdef TRM_DEBUG0
! 591: printf("%s: trm_reset", sc->sc_device.dv_xname);
! 592: #endif
! 593:
! 594: intflag = splbio();
! 595:
! 596: bus_space_write_1(iot, ioh, TRM_S1040_DMA_INTEN, 0);
! 597: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_INTEN, 0);
! 598:
! 599: trm_ResetSCSIBus(sc);
! 600: for (i = 0; i < 500; i++)
! 601: DELAY(1000);
! 602:
! 603: /*
! 604: * Enable all SCSI interrupts except EN_SCAM
! 605: */
! 606: bus_space_write_1(iot, ioh,
! 607: TRM_S1040_SCSI_INTEN,
! 608: (EN_SELECT | EN_SELTIMEOUT | EN_DISCONNECT | EN_RESELECTED |
! 609: EN_SCSIRESET | EN_BUSSERVICE | EN_CMDDONE));
! 610: /*
! 611: * Enable DMA interrupt
! 612: */
! 613: bus_space_write_1(iot, ioh, TRM_S1040_DMA_INTEN, EN_SCSIINTR);
! 614: /*
! 615: * Clear DMA FIFO
! 616: */
! 617: bus_space_write_1(iot, ioh, TRM_S1040_DMA_CONTROL, CLRXFIFO);
! 618: /*
! 619: * Clear SCSI FIFO
! 620: */
! 621: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL, DO_CLRFIFO);
! 622:
! 623: trm_ResetAllDevParam(sc);
! 624: trm_GoingSRB_Done(sc);
! 625: sc->pActiveDCB = NULL;
! 626:
! 627: /*
! 628: * RESET_DETECT, RESET_DONE, RESET_DEV
! 629: */
! 630: sc->sc_Flag = 0;
! 631: trm_StartWaitingSRB(sc);
! 632:
! 633: splx(intflag);
! 634: }
! 635:
! 636: /*
! 637: * ------------------------------------------------------------
! 638: * Function : trm_timeout
! 639: * Purpose : Prints a timeout message and aborts the timed out SCSI request
! 640: * Inputs : void * - A struct trm_scsi_req_q * structure pointer
! 641: * ------------------------------------------------------------
! 642: */
! 643: void
! 644: trm_timeout(void *arg1)
! 645: {
! 646: struct trm_scsi_req_q *pSRB;
! 647: struct scsi_xfer *xs;
! 648: struct trm_softc *sc;
! 649:
! 650: pSRB = (struct trm_scsi_req_q *)arg1;
! 651: xs = pSRB->xs;
! 652:
! 653: if (xs != NULL) {
! 654: sc = xs->sc_link->adapter_softc;
! 655: sc_print_addr(xs->sc_link);
! 656: printf("%s: SCSI OpCode 0x%02x for target %d lun %d timed out\n",
! 657: sc->sc_device.dv_xname, xs->cmd->opcode,
! 658: xs->sc_link->target, xs->sc_link->lun);
! 659: pSRB->SRBFlag |= TRM_SCSI_TIMED_OUT;
! 660: trm_FinishSRB(sc, pSRB);
! 661: trm_StartWaitingSRB(sc);
! 662: }
! 663: #ifdef TRM_DEBUG0
! 664: else
! 665: printf("%s: trm_timeout called with xs == NULL\n",
! 666: sc->sc_device.dv_xname);
! 667: #endif
! 668: }
! 669:
! 670: /*
! 671: * ------------------------------------------------------------
! 672: * Function : trm_StartSRB
! 673: * Purpose : Send the commands in the SRB to the device
! 674: * Inputs : struct trm_softc * -
! 675: * struct trm_scsi_req_q * -
! 676: * Return : 0 - SCSI processor is unoccupied
! 677: * 1 - SCSI processor is occupied with an SRB
! 678: * ------------------------------------------------------------
! 679: */
! 680: int
! 681: trm_StartSRB(struct trm_softc *sc, struct trm_scsi_req_q *pSRB)
! 682: {
! 683: const bus_space_handle_t ioh = sc->sc_iohandle;
! 684: const bus_space_tag_t iot = sc->sc_iotag;
! 685: struct trm_dcb *pDCB = pSRB->pSRBDCB;
! 686: u_int32_t tag_mask;
! 687: u_int8_t tag_id, scsicommand;
! 688:
! 689: #ifdef TRM_DEBUG0
! 690: printf("%s: trm_StartSRB. sc = %p, pDCB = %p, pSRB = %p\n",
! 691: sc->sc_device.dv_xname, sc, pDCB, pSRB);
! 692: #endif
! 693: /*
! 694: * If the queue is full or the SCSI processor has a pending interrupt
! 695: * then try again later.
! 696: */
! 697: if ((pDCB->DCBFlag & TRM_QUEUE_FULL) || (bus_space_read_2(iot, ioh,
! 698: TRM_S1040_SCSI_STATUS) & SCSIINTERRUPT))
! 699: return (1);
! 700:
! 701: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_HOSTID, sc->sc_AdaptSCSIID);
! 702: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_TARGETID, pDCB->target);
! 703: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_SYNC, pDCB->SyncPeriod);
! 704: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_OFFSET, pDCB->SyncOffset);
! 705:
! 706: if ((sc->pDCB[pDCB->target][0]->sc_link != NULL) &&
! 707: ((sc->pDCB[pDCB->target][0]->DCBFlag & TRM_QUIRKS_VALID) == 0)) {
! 708: sc->pDCB[pDCB->target][0]->DCBFlag |= TRM_QUIRKS_VALID;
! 709: trm_ResetDevParam(sc, sc->pDCB[pDCB->target][0], sc->pDCB[pDCB->target][0]->sc_link->quirks);
! 710: }
! 711:
! 712: /*
! 713: * Flush FIFO
! 714: */
! 715: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL, DO_CLRFIFO);
! 716:
! 717: sc->MsgCnt = 1;
! 718: sc->MsgBuf[0] = pDCB->IdentifyMsg;
! 719: if (((pSRB->xs->flags & SCSI_POLL) != 0) ||
! 720: (pSRB->CmdBlock[0] == INQUIRY) ||
! 721: (pSRB->CmdBlock[0] == REQUEST_SENSE))
! 722: sc->MsgBuf[0] &= ~MSG_IDENTIFY_DISCFLAG;
! 723:
! 724: scsicommand = SCMD_SEL_ATN;
! 725:
! 726: if ((pDCB->DCBFlag & (TRM_WIDE_NEGO_ENABLE | TRM_SYNC_NEGO_ENABLE)) != 0) {
! 727: scsicommand = SCMD_SEL_ATNSTOP;
! 728: pSRB->SRBState = TRM_MSGOUT;
! 729:
! 730: } else if ((pDCB->DCBFlag & TRM_USE_TAG_QUEUING) == 0) {
! 731: pDCB->DCBFlag |= TRM_QUEUE_FULL;
! 732:
! 733: } else if ((sc->MsgBuf[0] & MSG_IDENTIFY_DISCFLAG) != 0) {
! 734: if (pSRB->TagNumber == TRM_NO_TAG) {
! 735: for (tag_id=1, tag_mask=2; tag_id < 32; tag_id++, tag_mask <<= 1)
! 736: if ((tag_mask & pDCB->TagMask) == 0) {
! 737: pDCB->TagMask |= tag_mask;
! 738: pSRB->TagNumber = tag_id;
! 739: break;
! 740: }
! 741:
! 742: if (tag_id >= 32) {
! 743: pDCB->DCBFlag |= TRM_QUEUE_FULL;
! 744: sc->MsgCnt = 0;
! 745: return 1;
! 746: }
! 747: }
! 748:
! 749: /* TODO XXXX: Should send ORDERED_Q_TAG if metadata (non-block) i/o!? */
! 750: sc->MsgBuf[sc->MsgCnt++] = MSG_SIMPLE_Q_TAG;
! 751: sc->MsgBuf[sc->MsgCnt++] = pSRB->TagNumber;
! 752:
! 753: scsicommand = SCMD_SEL_ATN3;
! 754: }
! 755:
! 756: pSRB->SRBState = TRM_START;
! 757: pSRB->ScsiPhase = PH_BUS_FREE; /* SCSI bus free Phase */
! 758: sc->pActiveDCB = pDCB;
! 759: pDCB->pActiveSRB = pSRB;
! 760:
! 761: if (sc->MsgCnt > 0) {
! 762: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_FIFO, sc->MsgBuf[0]);
! 763: if (sc->MsgCnt > 1) {
! 764: DELAY(30);
! 765: bus_space_write_multi_1(iot, ioh, TRM_S1040_SCSI_FIFO, &sc->MsgBuf[1], sc->MsgCnt - 1);
! 766: }
! 767: sc->MsgCnt = 0;
! 768: }
! 769:
! 770: /*
! 771: * it's important for atn stop
! 772: */
! 773: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL, DO_DATALATCH | DO_HWRESELECT);
! 774: /*
! 775: * SCSI command
! 776: */
! 777: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_COMMAND, scsicommand);
! 778:
! 779: return 0;
! 780: }
! 781:
! 782: /*
! 783: * ------------------------------------------------------------
! 784: * Function : trm_Interrupt
! 785: * Purpose : Catch an interrupt from the adapter
! 786: * Process pending device interrupts.
! 787: * Inputs : void * - struct trm_softc * structure pointer
! 788: * ------------------------------------------------------------
! 789: */
! 790: int
! 791: trm_Interrupt(void *vsc)
! 792: {
! 793: void (*stateV)(struct trm_softc *, struct trm_scsi_req_q *, u_int8_t *);
! 794: struct trm_scsi_req_q *pSRB;
! 795: bus_space_handle_t ioh;
! 796: struct trm_softc *sc = (struct trm_softc *)vsc;
! 797: bus_space_tag_t iot;
! 798: u_int16_t phase;
! 799: u_int8_t scsi_status, scsi_intstatus;
! 800: int intflag;
! 801:
! 802: intflag = splbio();
! 803:
! 804: if (sc == NULL) {
! 805: splx(intflag);
! 806: return 0;
! 807: }
! 808:
! 809: ioh = sc->sc_iohandle;
! 810: iot = sc->sc_iotag;
! 811:
! 812: scsi_status = bus_space_read_2(iot, ioh, TRM_S1040_SCSI_STATUS);
! 813: if (!(scsi_status & SCSIINTERRUPT)) {
! 814: splx(intflag);
! 815: return 0;
! 816: }
! 817: scsi_intstatus = bus_space_read_1(iot, ioh, TRM_S1040_SCSI_INTSTATUS);
! 818:
! 819: #ifdef TRM_DEBUG0
! 820: printf("%s: trm_interrupt - scsi_status=0x%02x, scsi_intstatus=0x%02x\n",
! 821: sc->sc_device.dv_xname, scsi_status, scsi_intstatus);
! 822: #endif
! 823: if ((scsi_intstatus & (INT_SELTIMEOUT | INT_DISCONNECT)) != 0)
! 824: trm_Disconnect(sc);
! 825:
! 826: else if ((scsi_intstatus & INT_RESELECTED) != 0)
! 827: trm_Reselect(sc);
! 828:
! 829: else if ((scsi_intstatus & INT_SCSIRESET) != 0)
! 830: trm_ScsiRstDetect(sc);
! 831:
! 832: else if ((sc->pActiveDCB != NULL) && ((scsi_intstatus & (INT_BUSSERVICE | INT_CMDDONE)) != 0)) {
! 833: pSRB = sc->pActiveDCB->pActiveSRB;
! 834: /*
! 835: * software sequential machine
! 836: */
! 837: phase = (u_int16_t) pSRB->ScsiPhase; /* phase: */
! 838: /*
! 839: * 62037 or 62137
! 840: * call trm_SCSI_phase0[]... "phase entry"
! 841: * handle every phase before start transfer
! 842: */
! 843: stateV = trm_SCSI_phase0[phase];
! 844: stateV(sc, pSRB, &scsi_status);
! 845: /*
! 846: * if any exception occurred
! 847: * scsi_status will be modified to bus free phase
! 848: * new scsi_status transfer out from previous stateV
! 849: */
! 850: /*
! 851: * phase:0,1,2,3,4,5,6,7
! 852: */
! 853: pSRB->ScsiPhase = scsi_status & PHASEMASK;
! 854: phase = (u_int16_t) scsi_status & PHASEMASK;
! 855: /*
! 856: * call trm_SCSI_phase1[]... "phase entry"
! 857: * handle every phase do transfer
! 858: */
! 859: stateV = trm_SCSI_phase1[phase];
! 860: stateV(sc, pSRB, &scsi_status);
! 861:
! 862: } else {
! 863: splx(intflag);
! 864: return 0;
! 865: }
! 866:
! 867: splx(intflag);
! 868: return 1;
! 869: }
! 870:
! 871: /*
! 872: * ------------------------------------------------------------
! 873: * Function : trm_MsgOutPhase0
! 874: * Purpose : Check the state machine before sending a message out
! 875: * Inputs : struct trm_softc * -
! 876: * struct trm_scsi_req_q * -
! 877: * u_int8_t * - scsi status, set to PH_BUS_FREE if not ready
! 878: * ------------------------------------------------------------
! 879: */
! 880: void
! 881: trm_MsgOutPhase0(struct trm_softc *sc, struct trm_scsi_req_q *pSRB, u_int8_t *pscsi_status)
! 882: {
! 883: switch (pSRB->SRBState) {
! 884: case TRM_UNEXPECT_RESEL:
! 885: case TRM_ABORT_SENT:
! 886: *pscsi_status = PH_BUS_FREE; /* initial phase */
! 887: break;
! 888:
! 889: default:
! 890: break;
! 891: }
! 892: }
! 893:
! 894: /*
! 895: * ------------------------------------------------------------
! 896: * Function : trm_MsgOutPhase1
! 897: * Purpose : Write the message out to the bus
! 898: * Inputs : struct trm_softc * -
! 899: * struct trm_scsi_req_q * -
! 900: * u_int8_t * - unused
! 901: * ------------------------------------------------------------
! 902: */
! 903: void
! 904: trm_MsgOutPhase1(struct trm_softc *sc, struct trm_scsi_req_q *pSRB, u_int8_t *pscsi_status)
! 905: {
! 906: const bus_space_handle_t ioh = sc->sc_iohandle;
! 907: const bus_space_tag_t iot = sc->sc_iotag;
! 908: struct trm_dcb *pDCB = sc->pActiveDCB;
! 909:
! 910: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL, DO_CLRFIFO);
! 911:
! 912: if ((pDCB->DCBFlag & TRM_WIDE_NEGO_ENABLE) != 0) {
! 913: /*
! 914: * WIDE DATA TRANSFER REQUEST code (03h)
! 915: */
! 916: pDCB->DCBFlag &= ~TRM_WIDE_NEGO_ENABLE;
! 917: pDCB->DCBFlag |= TRM_DOING_WIDE_NEGO;
! 918:
! 919: sc->MsgBuf[0] = pDCB->IdentifyMsg & ~MSG_IDENTIFY_DISCFLAG;
! 920: sc->MsgBuf[1] = MSG_EXTENDED;
! 921: sc->MsgBuf[2] = MSG_EXT_WDTR_LEN;
! 922: sc->MsgBuf[3] = MSG_EXT_WDTR;
! 923:
! 924: if ((pDCB->DCBFlag & TRM_WIDE_NEGO_16BIT) == 0)
! 925: sc->MsgBuf[4] = MSG_EXT_WDTR_BUS_8_BIT;
! 926: else
! 927: sc->MsgBuf[4] = MSG_EXT_WDTR_BUS_16_BIT;
! 928:
! 929: sc->MsgCnt = 5;
! 930:
! 931: } else if ((pDCB->DCBFlag & TRM_SYNC_NEGO_ENABLE) != 0) {
! 932:
! 933: pDCB->DCBFlag &= ~TRM_SYNC_NEGO_ENABLE;
! 934: pDCB->DCBFlag |= TRM_DOING_SYNC_NEGO;
! 935:
! 936: sc->MsgCnt = 0;
! 937:
! 938: if ((pDCB->DCBFlag & TRM_WIDE_NEGO_DONE) == 0)
! 939: sc->MsgBuf[sc->MsgCnt++] = pDCB->IdentifyMsg & ~MSG_IDENTIFY_DISCFLAG;
! 940:
! 941: sc->MsgBuf[sc->MsgCnt++] = MSG_EXTENDED;
! 942: sc->MsgBuf[sc->MsgCnt++] = MSG_EXT_SDTR_LEN;
! 943: sc->MsgBuf[sc->MsgCnt++] = MSG_EXT_SDTR;
! 944: sc->MsgBuf[sc->MsgCnt++] = pDCB->MaxNegoPeriod;
! 945:
! 946: if (pDCB->MaxNegoPeriod > 0)
! 947: sc->MsgBuf[sc->MsgCnt++] = TRM_MAX_SYNC_OFFSET;
! 948: else
! 949: sc->MsgBuf[sc->MsgCnt++] = 0;
! 950: }
! 951:
! 952: if (sc->MsgCnt > 0) {
! 953: bus_space_write_multi_1(iot, ioh, TRM_S1040_SCSI_FIFO, &sc->MsgBuf[0], sc->MsgCnt);
! 954: if (sc->MsgBuf[0] == MSG_ABORT)
! 955: pSRB->SRBState = TRM_ABORT_SENT;
! 956: sc->MsgCnt = 0;
! 957: }
! 958: /*
! 959: * it's important for atn stop
! 960: */
! 961: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL, DO_DATALATCH);
! 962: /*
! 963: * Transfer information out
! 964: */
! 965: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_COMMAND, SCMD_FIFO_OUT);
! 966: }
! 967:
! 968: /*
! 969: * ------------------------------------------------------------
! 970: * Function : trm_CommandPhase1
! 971: * Purpose : Send commands to bus
! 972: * Inputs :
! 973: * ------------------------------------------------------------
! 974: */
! 975: void
! 976: trm_CommandPhase1(struct trm_softc *sc, struct trm_scsi_req_q *pSRB, u_int8_t *pscsi_status)
! 977: {
! 978: const bus_space_handle_t ioh = sc->sc_iohandle;
! 979: const bus_space_tag_t iot = sc->sc_iotag;
! 980:
! 981: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL, DO_CLRATN | DO_CLRFIFO);
! 982:
! 983: bus_space_write_multi_1(iot, ioh, TRM_S1040_SCSI_FIFO, &pSRB->CmdBlock[0], pSRB->ScsiCmdLen);
! 984:
! 985: pSRB->SRBState = TRM_COMMAND;
! 986: /*
! 987: * it's important for atn stop
! 988: */
! 989: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL, DO_DATALATCH);
! 990: /*
! 991: * Transfer information out
! 992: */
! 993: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_COMMAND, SCMD_FIFO_OUT);
! 994: }
! 995:
! 996: /*
! 997: * ------------------------------------------------------------
! 998: * Function : trm_DataOutPhase0
! 999: * Purpose : Ready for Data Out, clear FIFO
! 1000: * Inputs : u_int8_t * - SCSI status, used but not set
! 1001: * ------------------------------------------------------------
! 1002: */
! 1003: void
! 1004: trm_DataOutPhase0(struct trm_softc *sc, struct trm_scsi_req_q *pSRB, u_int8_t *pscsi_status)
! 1005: {
! 1006: const bus_space_handle_t ioh = sc->sc_iohandle;
! 1007: const bus_space_tag_t iot = sc->sc_iotag;
! 1008: struct SGentry *pseg;
! 1009: struct trm_dcb *pDCB;
! 1010: u_int32_t dLeftCounter, TempSRBXferredLength;
! 1011: u_int16_t scsi_status;
! 1012: u_int8_t TempDMAstatus, SGIndexTemp;
! 1013:
! 1014: dLeftCounter = 0;
! 1015:
! 1016: pDCB = pSRB->pSRBDCB;
! 1017: scsi_status = *pscsi_status;
! 1018:
! 1019: if (pSRB->SRBState != TRM_XFERPAD) {
! 1020: if ((scsi_status & PARITYERROR) != 0)
! 1021: pSRB->SRBFlag |= TRM_PARITY_ERROR;
! 1022: if ((scsi_status & SCSIXFERDONE) == 0) {
! 1023: /*
! 1024: * when data transfer from DMA FIFO to SCSI FIFO
! 1025: * if there was some data left in SCSI FIFO
! 1026: */
! 1027: dLeftCounter = (u_int32_t)(bus_space_read_1(
! 1028: iot, ioh, TRM_S1040_SCSI_FIFOCNT) & 0x1F);
! 1029: if (pDCB->SyncPeriod & WIDE_SYNC) {
! 1030: /*
! 1031: * if WIDE scsi SCSI FIFOCNT unit is word
! 1032: * so need to * 2
! 1033: */
! 1034: dLeftCounter <<= 1;
! 1035: }
! 1036: }
! 1037: /*
! 1038: * calculate all the residue data that not yet transferred
! 1039: * SCSI transfer counter + left in SCSI FIFO data
! 1040: *
! 1041: * .....TRM_S1040_SCSI_COUNTER (24bits)
! 1042: * The counter always decrement by one for every SCSI byte
! 1043: * transfer.
! 1044: * .....TRM_S1040_SCSI_FIFOCNT ( 5bits)
! 1045: * The counter is SCSI FIFO offset counter
! 1046: */
! 1047: dLeftCounter += bus_space_read_4(iot, ioh,
! 1048: TRM_S1040_SCSI_COUNTER);
! 1049: if (dLeftCounter == 1) {
! 1050: dLeftCounter = 0;
! 1051: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL,
! 1052: DO_CLRFIFO);
! 1053: }
! 1054: if (dLeftCounter == 0 ||
! 1055: (scsi_status & SCSIXFERCNT_2_ZERO) != 0) {
! 1056: TempDMAstatus = bus_space_read_1(iot,
! 1057: ioh, TRM_S1040_DMA_STATUS);
! 1058: while ((TempDMAstatus & DMAXFERCOMP) == 0) {
! 1059: TempDMAstatus = bus_space_read_1(iot,
! 1060: ioh, TRM_S1040_DMA_STATUS);
! 1061: }
! 1062: pSRB->SRBTotalXferLength = 0;
! 1063: } else {
! 1064: /*
! 1065: * Update SG list
! 1066: */
! 1067: /*
! 1068: * if transfer not yet complete
! 1069: * there were some data residue in SCSI FIFO or
! 1070: * SCSI transfer counter not empty
! 1071: */
! 1072: if (pSRB->SRBTotalXferLength != dLeftCounter) {
! 1073: /*
! 1074: * data that had transferred length
! 1075: */
! 1076: TempSRBXferredLength = pSRB->SRBTotalXferLength
! 1077: - dLeftCounter;
! 1078: /*
! 1079: * next time to be transferred length
! 1080: */
! 1081: pSRB->SRBTotalXferLength = dLeftCounter;
! 1082: /*
! 1083: * parsing from last time disconnect SRBSGIndex
! 1084: */
! 1085: pseg = &pSRB->SegmentX[pSRB->SRBSGIndex];
! 1086: for (SGIndexTemp = pSRB->SRBSGIndex;
! 1087: SGIndexTemp < pSRB->SRBSGCount;
! 1088: SGIndexTemp++) {
! 1089: /*
! 1090: * find last time which SG transfer be
! 1091: * disconnect
! 1092: */
! 1093: if (TempSRBXferredLength >= pseg->length)
! 1094: TempSRBXferredLength -= pseg->length;
! 1095: else {
! 1096: /*
! 1097: * update last time disconnected
! 1098: * SG list
! 1099: */
! 1100: /*
! 1101: * residue data length
! 1102: */
! 1103: pseg->length -=
! 1104: TempSRBXferredLength;
! 1105: /*
! 1106: * residue data pointer
! 1107: */
! 1108: pseg->address +=
! 1109: TempSRBXferredLength;
! 1110: pSRB->SRBSGIndex = SGIndexTemp;
! 1111: break;
! 1112: }
! 1113: pseg++;
! 1114: }
! 1115: }
! 1116: }
! 1117: }
! 1118: bus_space_write_1(iot, ioh, TRM_S1040_DMA_CONTROL, STOPDMAXFER);
! 1119: }
! 1120:
! 1121: /*
! 1122: * ------------------------------------------------------------
! 1123: * Function : trm_DataOutPhase1
! 1124: * Purpose : Transfers data out, calls trm_DataIO_transfer
! 1125: * Inputs :
! 1126: * ------------------------------------------------------------
! 1127: */
! 1128: void
! 1129: trm_DataOutPhase1(struct trm_softc *sc, struct trm_scsi_req_q *pSRB, u_int8_t *pscsi_status)
! 1130: {
! 1131: trm_DataIO_transfer(sc, pSRB, XFERDATAOUT);
! 1132: }
! 1133:
! 1134: /*
! 1135: * ------------------------------------------------------------
! 1136: * Function : trm_DataInPhase0
! 1137: * Purpose : Prepare for reading data in from bus
! 1138: * Inputs :
! 1139: * ------------------------------------------------------------
! 1140: */
! 1141: void
! 1142: trm_DataInPhase0(struct trm_softc *sc, struct trm_scsi_req_q *pSRB, u_int8_t *pscsi_status)
! 1143: {
! 1144: const bus_space_handle_t ioh = sc->sc_iohandle;
! 1145: const bus_space_tag_t iot = sc->sc_iotag;
! 1146: struct SGentry *pseg;
! 1147: u_int32_t TempSRBXferredLength, dLeftCounter;
! 1148: u_int16_t scsi_status;
! 1149: u_int8_t SGIndexTemp;
! 1150:
! 1151: dLeftCounter = 0;
! 1152:
! 1153: scsi_status = *pscsi_status;
! 1154: if (pSRB->SRBState != TRM_XFERPAD) {
! 1155: if ((scsi_status & PARITYERROR) != 0)
! 1156: pSRB->SRBFlag |= TRM_PARITY_ERROR;
! 1157: dLeftCounter += bus_space_read_4(iot, ioh,
! 1158: TRM_S1040_SCSI_COUNTER);
! 1159: if (dLeftCounter == 0 ||
! 1160: (scsi_status & SCSIXFERCNT_2_ZERO) != 0) {
! 1161: while ((bus_space_read_1(iot, ioh, TRM_S1040_DMA_STATUS) & DMAXFERCOMP) == 0)
! 1162: ;
! 1163: pSRB->SRBTotalXferLength = 0;
! 1164: } else {
! 1165: /*
! 1166: * phase changed
! 1167: *
! 1168: * parsing the case:
! 1169: * when a transfer not yet complete
! 1170: * but be disconnected by uper layer
! 1171: * if transfer not yet complete
! 1172: * there were some data residue in SCSI FIFO or
! 1173: * SCSI transfer counter not empty
! 1174: */
! 1175: if (pSRB->SRBTotalXferLength != dLeftCounter) {
! 1176: /*
! 1177: * data that had transferred length
! 1178: */
! 1179: TempSRBXferredLength = pSRB->SRBTotalXferLength
! 1180: - dLeftCounter;
! 1181: /*
! 1182: * next time to be transferred length
! 1183: */
! 1184: pSRB->SRBTotalXferLength = dLeftCounter;
! 1185: /*
! 1186: * parsing from last time disconnect SRBSGIndex
! 1187: */
! 1188: pseg = &pSRB->SegmentX[pSRB->SRBSGIndex];
! 1189: for (SGIndexTemp = pSRB->SRBSGIndex;
! 1190: SGIndexTemp < pSRB->SRBSGCount;
! 1191: SGIndexTemp++) {
! 1192: /*
! 1193: * find last time which SG transfer be
! 1194: * disconnect
! 1195: */
! 1196: if (TempSRBXferredLength >=
! 1197: pseg->length) {
! 1198: TempSRBXferredLength -= pseg->length;
! 1199: } else {
! 1200: /*
! 1201: * update last time disconnected
! 1202: * SG list
! 1203: *
! 1204: * residue data length
! 1205: */
! 1206: pseg->length -= TempSRBXferredLength;
! 1207: /*
! 1208: * residue data pointer
! 1209: */
! 1210: pseg->address += TempSRBXferredLength;
! 1211: pSRB->SRBSGIndex = SGIndexTemp;
! 1212: break;
! 1213: }
! 1214: pseg++;
! 1215: }
! 1216: }
! 1217: }
! 1218: }
! 1219: }
! 1220:
! 1221: /*
! 1222: * ------------------------------------------------------------
! 1223: * Function : trm_DataInPhase1
! 1224: * Purpose : Transfer data in from bus, calls trm_DataIO_transfer
! 1225: * Inputs :
! 1226: * ------------------------------------------------------------
! 1227: */
! 1228: void
! 1229: trm_DataInPhase1(struct trm_softc *sc, struct trm_scsi_req_q *pSRB, u_int8_t *pscsi_status)
! 1230: {
! 1231: trm_DataIO_transfer(sc, pSRB, XFERDATAIN);
! 1232: }
! 1233:
! 1234: /*
! 1235: * ------------------------------------------------------------
! 1236: * Function : trm_DataIO_transfer
! 1237: * Purpose :
! 1238: * Inputs :
! 1239: * ------------------------------------------------------------
! 1240: */
! 1241: void
! 1242: trm_DataIO_transfer(struct trm_softc *sc, struct trm_scsi_req_q *pSRB, u_int16_t ioDir)
! 1243: {
! 1244: const bus_space_handle_t ioh = sc->sc_iohandle;
! 1245: const bus_space_tag_t iot = sc->sc_iotag;
! 1246: struct trm_dcb *pDCB = pSRB->pSRBDCB;
! 1247: u_int8_t bval;
! 1248:
! 1249: if (pSRB->SRBSGIndex < pSRB->SRBSGCount) {
! 1250: if (pSRB->SRBTotalXferLength != 0) {
! 1251: /*
! 1252: * load what physical address of Scatter/Gather list
! 1253: * table want to be transfer
! 1254: */
! 1255: pSRB->SRBState = TRM_DATA_XFER;
! 1256: bus_space_write_4(iot, ioh, TRM_S1040_DMA_XHIGHADDR, 0);
! 1257: bus_space_write_4(iot, ioh,
! 1258: TRM_S1040_DMA_XLOWADDR, (pSRB->SRBSGPhyAddr +
! 1259: ((u_int32_t)pSRB->SRBSGIndex << 3)));
! 1260: /*
! 1261: * load how many bytes in the Scatter/Gather list table
! 1262: */
! 1263: bus_space_write_4(iot, ioh, TRM_S1040_DMA_XCNT,
! 1264: ((u_int32_t)(pSRB->SRBSGCount -
! 1265: pSRB->SRBSGIndex) << 3));
! 1266: /*
! 1267: * load total transfer length (24bits,
! 1268: * pSRB->SRBTotalXferLength) max value 16Mbyte
! 1269: */
! 1270: bus_space_write_4(iot, ioh,
! 1271: TRM_S1040_SCSI_COUNTER, pSRB->SRBTotalXferLength);
! 1272: /*
! 1273: * Start DMA transfer
! 1274: */
! 1275: bus_space_write_2(iot,ioh,TRM_S1040_DMA_COMMAND, ioDir);
! 1276: /* bus_space_write_2(iot, ioh,
! 1277: TRM_S1040_DMA_CONTROL, STARTDMAXFER);*/
! 1278: /*
! 1279: * Set the transfer bus and direction
! 1280: */
! 1281: bval = ioDir == XFERDATAOUT ? SCMD_DMA_OUT :SCMD_DMA_IN;
! 1282: } else {
! 1283: /*
! 1284: * xfer pad
! 1285: */
! 1286: if (pSRB->SRBSGCount)
! 1287: pSRB->AdaptStatus = TRM_OVER_UNDER_RUN;
! 1288:
! 1289: if (pDCB->SyncPeriod & WIDE_SYNC) {
! 1290: bus_space_write_4(iot, ioh,
! 1291: TRM_S1040_SCSI_COUNTER, 2);
! 1292: } else {
! 1293: bus_space_write_4(iot, ioh,
! 1294: TRM_S1040_SCSI_COUNTER, 1);
! 1295: }
! 1296:
! 1297: if (ioDir == XFERDATAOUT) {
! 1298: bus_space_write_2(iot,
! 1299: ioh, TRM_S1040_SCSI_FIFO, 0);
! 1300: } else {
! 1301: bus_space_read_2(iot,
! 1302: ioh, TRM_S1040_SCSI_FIFO);
! 1303: }
! 1304: pSRB->SRBState = TRM_XFERPAD;
! 1305: /*
! 1306: * Set the transfer bus and direction
! 1307: */
! 1308: bval = ioDir == XFERDATAOUT ? SCMD_FIFO_OUT : SCMD_FIFO_IN;
! 1309: }
! 1310: /*
! 1311: * it's important for atn stop
! 1312: */
! 1313: bus_space_write_2(iot,ioh,TRM_S1040_SCSI_CONTROL, DO_DATALATCH);
! 1314: /*
! 1315: * Tell the bus to do the transfer
! 1316: */
! 1317: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_COMMAND, bval);
! 1318: }
! 1319: }
! 1320:
! 1321: /*
! 1322: * ------------------------------------------------------------
! 1323: * Function : trm_StatusPhase0
! 1324: * Purpose : Update Target Status with data from SCSI FIFO
! 1325: * Inputs : u_int8_t * - Set to PH_BUS_FREE
! 1326: * ------------------------------------------------------------
! 1327: */
! 1328: void
! 1329: trm_StatusPhase0(struct trm_softc *sc, struct trm_scsi_req_q *pSRB, u_int8_t *pscsi_status)
! 1330: {
! 1331: const bus_space_handle_t ioh = sc->sc_iohandle;
! 1332: const bus_space_tag_t iot = sc->sc_iotag;
! 1333:
! 1334: pSRB->TargetStatus = bus_space_read_1(iot, ioh, TRM_S1040_SCSI_FIFO);
! 1335:
! 1336: pSRB->SRBState = TRM_COMPLETED;
! 1337: /*
! 1338: * initial phase
! 1339: */
! 1340: *pscsi_status = PH_BUS_FREE;
! 1341: /*
! 1342: * it's important for atn stop
! 1343: */
! 1344: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL, DO_DATALATCH);
! 1345: /*
! 1346: * Tell bus that the message was accepted
! 1347: */
! 1348: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_COMMAND, SCMD_MSGACCEPT);
! 1349: }
! 1350:
! 1351: /*
! 1352: * ------------------------------------------------------------
! 1353: * Function : trm_StatusPhase1
! 1354: * Purpose : Clear FIFO of DMA and SCSI
! 1355: * Inputs :
! 1356: * ------------------------------------------------------------
! 1357: */
! 1358: void
! 1359: trm_StatusPhase1(struct trm_softc *sc, struct trm_scsi_req_q *pSRB, u_int8_t *pscsi_status)
! 1360: {
! 1361: const bus_space_handle_t ioh = sc->sc_iohandle;
! 1362: const bus_space_tag_t iot = sc->sc_iotag;
! 1363:
! 1364: if ((bus_space_read_2(iot, ioh, TRM_S1040_DMA_COMMAND) & 0x0001) != 0) {
! 1365: if ((bus_space_read_1(iot, ioh, TRM_S1040_SCSI_FIFOCNT) & 0x40)
! 1366: == 0) {
! 1367: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL,
! 1368: DO_CLRFIFO);
! 1369: }
! 1370: if ((bus_space_read_2(iot, ioh,
! 1371: TRM_S1040_DMA_FIFOCNT) & 0x8000) == 0) {
! 1372: bus_space_write_1(iot, ioh,
! 1373: TRM_S1040_DMA_CONTROL, CLRXFIFO);
! 1374: }
! 1375: } else {
! 1376: if ((bus_space_read_2(iot, ioh,
! 1377: TRM_S1040_DMA_FIFOCNT) & 0x8000) == 0) {
! 1378: bus_space_write_1(iot, ioh,
! 1379: TRM_S1040_DMA_CONTROL, CLRXFIFO);
! 1380: }
! 1381: if ((bus_space_read_1(iot, ioh,
! 1382: TRM_S1040_SCSI_FIFOCNT) & 0x40) == 0) {
! 1383: bus_space_write_2(iot, ioh,
! 1384: TRM_S1040_SCSI_CONTROL, DO_CLRFIFO);
! 1385: }
! 1386: }
! 1387: pSRB->SRBState = TRM_STATUS;
! 1388: /*
! 1389: * it's important for atn stop
! 1390: */
! 1391: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL, DO_DATALATCH);
! 1392: /*
! 1393: * Tell the bus that the command is complete
! 1394: */
! 1395: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_COMMAND, SCMD_COMP);
! 1396: }
! 1397:
! 1398: /*
! 1399: * ------------------------------------------------------------
! 1400: * Function : trm_MsgInPhase0
! 1401: * Purpose :
! 1402: * Inputs :
! 1403: *
! 1404: * extended message codes:
! 1405: * code description
! 1406: * ---- -----------
! 1407: * 02h Reserved
! 1408: * 00h MODIFY DATA POINTER
! 1409: * 01h SYNCHRONOUS DATA TRANSFER REQUEST
! 1410: * 03h WIDE DATA TRANSFER REQUEST
! 1411: * 04h - 7Fh Reserved
! 1412: * 80h - FFh Vendor specific
! 1413: *
! 1414: * ------------------------------------------------------------
! 1415: */
! 1416: void
! 1417: trm_MsgInPhase0(struct trm_softc *sc, struct trm_scsi_req_q *pSRB, u_int8_t *pscsi_status)
! 1418: {
! 1419: const bus_space_handle_t ioh = sc->sc_iohandle;
! 1420: const bus_space_tag_t iot = sc->sc_iotag;
! 1421: struct trm_dcb *pDCB;
! 1422: u_int8_t message_in_code, bIndex, message_in_tag_id;
! 1423:
! 1424: pDCB = sc->pActiveDCB;
! 1425:
! 1426: message_in_code = bus_space_read_1(iot, ioh, TRM_S1040_SCSI_FIFO);
! 1427:
! 1428: if (pSRB->SRBState != TRM_EXTEND_MSGIN) {
! 1429: switch (message_in_code) {
! 1430: case MSG_DISCONNECT:
! 1431: pSRB->SRBState = TRM_DISCONNECTED;
! 1432: break;
! 1433:
! 1434: case MSG_EXTENDED:
! 1435: case MSG_SIMPLE_Q_TAG:
! 1436: case MSG_HEAD_OF_Q_TAG:
! 1437: case MSG_ORDERED_Q_TAG:
! 1438: pSRB->SRBState = TRM_EXTEND_MSGIN;
! 1439: /*
! 1440: * extended message (01h)
! 1441: */
! 1442: bzero(&sc->MsgBuf[0], sizeof(sc->MsgBuf));
! 1443: sc->MsgBuf[0] = message_in_code;
! 1444: sc->MsgCnt = 1;
! 1445: /*
! 1446: * extended message length (n)
! 1447: */
! 1448: break;
! 1449:
! 1450: case MSG_MESSAGE_REJECT:
! 1451: /*
! 1452: * Reject message
! 1453: */
! 1454: if ((pDCB->DCBFlag & TRM_DOING_WIDE_NEGO) != 0) {
! 1455: /*
! 1456: * do wide nego reject
! 1457: */
! 1458: pDCB = pSRB->pSRBDCB;
! 1459:
! 1460: pDCB->DCBFlag &= ~TRM_DOING_WIDE_NEGO;
! 1461: pDCB->DCBFlag |= TRM_WIDE_NEGO_DONE;
! 1462:
! 1463: if ((pDCB->DCBFlag & TRM_SYNC_NEGO_ENABLE) != 0) {
! 1464: /*
! 1465: * Set ATN, in case ATN was clear
! 1466: */
! 1467: pSRB->SRBState = TRM_MSGOUT;
! 1468: bus_space_write_2(iot, ioh,
! 1469: TRM_S1040_SCSI_CONTROL, DO_SETATN);
! 1470: } else {
! 1471: /*
! 1472: * Clear ATN
! 1473: */
! 1474: bus_space_write_2(iot, ioh,
! 1475: TRM_S1040_SCSI_CONTROL, DO_CLRATN);
! 1476: }
! 1477:
! 1478: } else if ((pDCB->DCBFlag & TRM_DOING_SYNC_NEGO) != 0) {
! 1479: /*
! 1480: * do sync nego reject
! 1481: */
! 1482: pDCB = pSRB->pSRBDCB;
! 1483:
! 1484: pDCB->DCBFlag &= ~TRM_DOING_SYNC_NEGO;
! 1485:
! 1486: pDCB->SyncPeriod = 0;
! 1487: pDCB->SyncOffset = 0;
! 1488:
! 1489: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL, DO_CLRATN);
! 1490: goto re_prog;
! 1491: }
! 1492: break;
! 1493:
! 1494: case MSG_IGN_WIDE_RESIDUE:
! 1495: bus_space_write_4(iot, ioh, TRM_S1040_SCSI_COUNTER, 1);
! 1496: bus_space_read_1(iot, ioh, TRM_S1040_SCSI_FIFO);
! 1497: break;
! 1498:
! 1499: default:
! 1500: break;
! 1501: }
! 1502:
! 1503: } else {
! 1504:
! 1505: /*
! 1506: * We are collecting an extended message. Save the latest byte and then
! 1507: * check to see if the message is complete. If so, process it.
! 1508: */
! 1509: sc->MsgBuf[sc->MsgCnt++] = message_in_code;
! 1510: #ifdef TRM_DEBUG0
! 1511: printf("%s: sc->MsgBuf = 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
! 1512: sc->sc_device.dv_xname,
! 1513: sc->MsgBuf[0], sc->MsgBuf[1], sc->MsgBuf[2], sc->MsgBuf[3], sc->MsgBuf[4], sc->MsgBuf[5] );
! 1514: #endif
! 1515: switch (sc->MsgBuf[0]) {
! 1516: case MSG_SIMPLE_Q_TAG:
! 1517: case MSG_HEAD_OF_Q_TAG:
! 1518: case MSG_ORDERED_Q_TAG:
! 1519: if (sc->MsgCnt == 2) {
! 1520: pSRB->SRBState = TRM_FREE;
! 1521: message_in_tag_id = sc->MsgBuf[1];
! 1522: sc->MsgCnt = 0;
! 1523: TAILQ_FOREACH(pSRB, &sc->goingSRB, link) {
! 1524: if ((pSRB->pSRBDCB == pDCB) && (pSRB->TagNumber == message_in_tag_id))
! 1525: break;
! 1526: }
! 1527: if ((pSRB != NULL) && (pSRB->SRBState == TRM_DISCONNECTED)) {
! 1528: pDCB->pActiveSRB = pSRB;
! 1529: pSRB->SRBState = TRM_DATA_XFER;
! 1530: } else {
! 1531: pSRB = &sc->SRB[0];
! 1532: pSRB->SRBState = TRM_UNEXPECT_RESEL;
! 1533: pDCB->pActiveSRB = pSRB;
! 1534: trm_EnableMsgOut(sc, MSG_ABORT_TAG);
! 1535: }
! 1536: }
! 1537: break;
! 1538:
! 1539: case MSG_EXTENDED:
! 1540: /* TODO XXXX: Correctly handling target initiated negotiations? */
! 1541: if ((sc->MsgBuf[2] == MSG_EXT_WDTR) && (sc->MsgCnt == 4)) {
! 1542: /*
! 1543: * ======================================
! 1544: * WIDE DATA TRANSFER REQUEST
! 1545: * ======================================
! 1546: * byte 0 : Extended message (01h)
! 1547: * byte 1 : Extended message length (02h)
! 1548: * byte 2 : WIDE DATA TRANSFER code (03h)
! 1549: * byte 3 : Transfer width exponent
! 1550: */
! 1551:
! 1552: pSRB->SRBState = TRM_FREE;
! 1553: pDCB->DCBFlag &= ~(TRM_WIDE_NEGO_ENABLE | TRM_DOING_WIDE_NEGO);
! 1554:
! 1555: if (sc->MsgBuf[1] != MSG_EXT_WDTR_LEN)
! 1556: goto reject_offer;
! 1557:
! 1558: switch (sc->MsgBuf[3]) {
! 1559: case MSG_EXT_WDTR_BUS_32_BIT:
! 1560: if ((pDCB->DCBFlag & TRM_WIDE_NEGO_16BIT) == 0)
! 1561: sc->MsgBuf[3] = MSG_EXT_WDTR_BUS_8_BIT;
! 1562: else
! 1563: sc->MsgBuf[3] = MSG_EXT_WDTR_BUS_16_BIT;
! 1564: break;
! 1565:
! 1566: case MSG_EXT_WDTR_BUS_16_BIT:
! 1567: if ((pDCB->DCBFlag & TRM_WIDE_NEGO_16BIT) == 0) {
! 1568: sc->MsgBuf[3] = MSG_EXT_WDTR_BUS_8_BIT;
! 1569: break;
! 1570: }
! 1571: pDCB->SyncPeriod |= WIDE_SYNC;
! 1572: /* FALL THROUGH == ACCEPT OFFER */
! 1573:
! 1574: case MSG_EXT_WDTR_BUS_8_BIT:
! 1575: pSRB->SRBState = TRM_MSGOUT;
! 1576: pDCB->DCBFlag |= (TRM_SYNC_NEGO_ENABLE | TRM_WIDE_NEGO_DONE);
! 1577:
! 1578: if (pDCB->MaxNegoPeriod == 0) {
! 1579: pDCB->SyncPeriod = 0;
! 1580: pDCB->SyncOffset = 0;
! 1581: goto re_prog;
! 1582: }
! 1583: break;
! 1584:
! 1585: default:
! 1586: pDCB->DCBFlag &= ~TRM_WIDE_NEGO_ENABLE;
! 1587: pDCB->DCBFlag |= TRM_WIDE_NEGO_DONE;
! 1588: reject_offer:
! 1589: sc->MsgCnt = 1;
! 1590: sc->MsgBuf[0] = MSG_MESSAGE_REJECT;
! 1591: break;
! 1592: }
! 1593:
! 1594: /* Echo accepted offer, or send revised offer */
! 1595: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL, DO_SETATN);
! 1596:
! 1597: } else if ((sc->MsgBuf[2] == MSG_EXT_SDTR) && (sc->MsgCnt == 5)) {
! 1598: /*
! 1599: * =================================
! 1600: * SYNCHRONOUS DATA TRANSFER REQUEST
! 1601: * =================================
! 1602: * byte 0 : Extended message (01h)
! 1603: * byte 1 : Extended message length (03)
! 1604: * byte 2 : SYNCHRONOUS DATA TRANSFER code (01h)
! 1605: * byte 3 : Transfer period factor
! 1606: * byte 4 : REQ/ACK offset
! 1607: */
! 1608:
! 1609: pSRB->SRBState = TRM_FREE;
! 1610: pDCB->DCBFlag &= ~(TRM_SYNC_NEGO_ENABLE | TRM_DOING_SYNC_NEGO);
! 1611:
! 1612: if (sc->MsgBuf[1] != MSG_EXT_SDTR_LEN)
! 1613: goto reject_offer;
! 1614:
! 1615: if ((sc->MsgBuf[3] == 0) || (sc->MsgBuf[4] == 0)) {
! 1616: /*
! 1617: * Asynchronous transfers
! 1618: */
! 1619: pDCB->SyncPeriod = 0;
! 1620: pDCB->SyncOffset = 0;
! 1621:
! 1622: } else {
! 1623: /*
! 1624: * Synchronous transfers
! 1625: */
! 1626: /*
! 1627: * REQ/ACK offset
! 1628: */
! 1629: pDCB->SyncOffset = sc->MsgBuf[4];
! 1630:
! 1631: for (bIndex = 0; bIndex < 7; bIndex++)
! 1632: if (sc->MsgBuf[3] <= trm_clock_period[bIndex])
! 1633: break;
! 1634:
! 1635: pDCB->SyncPeriod |= (bIndex | ALT_SYNC);
! 1636: }
! 1637:
! 1638: re_prog: /*
! 1639: * program SCSI control register
! 1640: */
! 1641: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_SYNC, pDCB->SyncPeriod);
! 1642: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_OFFSET, pDCB->SyncOffset);
! 1643:
! 1644: trm_SetXferParams(sc, pDCB, (pDCB->DCBFlag & TRM_QUIRKS_VALID));
! 1645: }
! 1646: break;
! 1647:
! 1648: default:
! 1649: break;
! 1650: }
! 1651: }
! 1652:
! 1653: /*
! 1654: * initial phase
! 1655: */
! 1656: *pscsi_status = PH_BUS_FREE;
! 1657: /*
! 1658: * it's important for atn stop
! 1659: */
! 1660: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL, DO_DATALATCH);
! 1661: /*
! 1662: * Tell bus that the message was accepted
! 1663: */
! 1664: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_COMMAND, SCMD_MSGACCEPT);
! 1665: }
! 1666:
! 1667: /*
! 1668: * ------------------------------------------------------------
! 1669: * Function : trm_MsgInPhase1
! 1670: * Purpose : Clear the FIFO
! 1671: * Inputs :
! 1672: * ------------------------------------------------------------
! 1673: */
! 1674: void
! 1675: trm_MsgInPhase1(struct trm_softc *sc, struct trm_scsi_req_q *pSRB, u_int8_t *pscsi_status)
! 1676: {
! 1677: const bus_space_handle_t ioh = sc->sc_iohandle;
! 1678: const bus_space_tag_t iot = sc->sc_iotag;
! 1679:
! 1680: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL, DO_CLRFIFO);
! 1681: bus_space_write_4(iot, ioh, TRM_S1040_SCSI_COUNTER, 1);
! 1682:
! 1683: /*
! 1684: * it's important for atn stop
! 1685: */
! 1686: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL, DO_DATALATCH);
! 1687: /*
! 1688: * SCSI command
! 1689: */
! 1690: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_COMMAND, SCMD_FIFO_IN);
! 1691: }
! 1692:
! 1693: /*
! 1694: * ------------------------------------------------------------
! 1695: * Function : trm_Nop
! 1696: * Purpose : EMPTY
! 1697: * Inputs :
! 1698: * ------------------------------------------------------------
! 1699: */
! 1700: void
! 1701: trm_Nop(struct trm_softc *sc, struct trm_scsi_req_q *pSRB, u_int8_t *pscsi_status)
! 1702: {
! 1703: }
! 1704:
! 1705: /*
! 1706: * ------------------------------------------------------------
! 1707: * Function : trm_SetXferParams
! 1708: * Purpose : Set the Sync period, offset and mode for each device that has
! 1709: * the same target as the given one (struct trm_dcb *)
! 1710: * Inputs :
! 1711: * ------------------------------------------------------------
! 1712: */
! 1713: void
! 1714: trm_SetXferParams(struct trm_softc *sc, struct trm_dcb *pDCB, int print_info)
! 1715: {
! 1716: struct trm_dcb *pDCBTemp;
! 1717: int lun, target;
! 1718:
! 1719: /*
! 1720: * set all lun device's period, offset
! 1721: */
! 1722: #ifdef TRM_DEBUG0
! 1723: printf("%s: trm_SetXferParams\n", sc->sc_device.dv_xname);
! 1724: #endif
! 1725:
! 1726: target = pDCB->target;
! 1727: for(lun = 0; lun < TRM_MAX_LUNS; lun++) {
! 1728: pDCBTemp = sc->pDCB[target][lun];
! 1729: if (pDCBTemp != NULL) {
! 1730: pDCBTemp->DevMode = pDCB->DevMode;
! 1731: pDCBTemp->MaxNegoPeriod = pDCB->MaxNegoPeriod;
! 1732: pDCBTemp->SyncPeriod = pDCB->SyncPeriod;
! 1733: pDCBTemp->SyncOffset = pDCB->SyncOffset;
! 1734: pDCBTemp->DCBFlag = pDCB->DCBFlag;
! 1735: }
! 1736: }
! 1737:
! 1738: if (print_info)
! 1739: trm_print_info(sc, pDCB);
! 1740: }
! 1741:
! 1742: /*
! 1743: * ------------------------------------------------------------
! 1744: * Function : trm_Disconnect
! 1745: * Purpose :
! 1746: * Inputs :
! 1747: *
! 1748: * ---SCSI bus phase
! 1749: * PH_DATA_OUT 0x00 Data out phase
! 1750: * PH_DATA_IN 0x01 Data in phase
! 1751: * PH_COMMAND 0x02 Command phase
! 1752: * PH_STATUS 0x03 Status phase
! 1753: * PH_BUS_FREE 0x04 Invalid phase used as bus free
! 1754: * PH_BUS_FREE 0x05 Invalid phase used as bus free
! 1755: * PH_MSG_OUT 0x06 Message out phase
! 1756: * PH_MSG_IN 0x07 Message in phase
! 1757: * ------------------------------------------------------------
! 1758: */
! 1759: void
! 1760: trm_Disconnect(struct trm_softc *sc)
! 1761: {
! 1762: const bus_space_handle_t ioh = sc->sc_iohandle;
! 1763: struct trm_scsi_req_q *pSRB, *pNextSRB;
! 1764: const bus_space_tag_t iot = sc->sc_iotag;
! 1765: struct trm_dcb *pDCB;
! 1766: int j;
! 1767:
! 1768: #ifdef TRM_DEBUG0
! 1769: printf("%s: trm_Disconnect\n", sc->sc_device.dv_xname);
! 1770: #endif
! 1771:
! 1772: pDCB = sc->pActiveDCB;
! 1773: if (pDCB == NULL) {
! 1774: /* TODO: Why use a loop? Why not use DELAY(400)? */
! 1775: for(j = 400; j > 0; --j)
! 1776: DELAY(1); /* 1 msec */
! 1777: bus_space_write_2(iot, ioh,
! 1778: TRM_S1040_SCSI_CONTROL, (DO_CLRFIFO | DO_HWRESELECT));
! 1779: return;
! 1780: }
! 1781:
! 1782: pSRB = pDCB->pActiveSRB;
! 1783: sc->pActiveDCB = NULL;
! 1784: pSRB->ScsiPhase = PH_BUS_FREE; /* SCSI bus free Phase */
! 1785: bus_space_write_2(iot, ioh,
! 1786: TRM_S1040_SCSI_CONTROL, (DO_CLRFIFO | DO_HWRESELECT));
! 1787: DELAY(100);
! 1788:
! 1789: switch (pSRB->SRBState) {
! 1790: case TRM_UNEXPECT_RESEL:
! 1791: pSRB->SRBState = TRM_FREE;
! 1792: break;
! 1793:
! 1794: case TRM_ABORT_SENT:
! 1795: pSRB = TAILQ_FIRST(&sc->goingSRB);
! 1796: while (pSRB != NULL) {
! 1797: /*
! 1798: * Need to save pNextSRB because trm_FinishSRB() puts
! 1799: * pSRB in freeSRB queue, and thus its links no longer
! 1800: * point to members of the goingSRB queue. This is why
! 1801: * TAILQ_FOREACH() will not work for this traversal.
! 1802: */
! 1803: pNextSRB = TAILQ_NEXT(pSRB, link);
! 1804: if (pSRB->pSRBDCB == pDCB) {
! 1805: /* TODO XXXX: Is TIMED_OUT the best state to report? */
! 1806: pSRB->SRBFlag |= TRM_SCSI_TIMED_OUT;
! 1807: trm_FinishSRB(sc, pSRB);
! 1808: }
! 1809: pSRB = pNextSRB;
! 1810: }
! 1811: break;
! 1812:
! 1813: case TRM_START:
! 1814: case TRM_MSGOUT:
! 1815: /*
! 1816: * Selection time out
! 1817: */
! 1818: /* If not polling just keep trying until xs->stimeout expires */
! 1819: if ((pSRB->xs->flags & SCSI_POLL) == 0) {
! 1820: trm_RewaitSRB(sc, pSRB);
! 1821: } else {
! 1822: pSRB->TargetStatus = TRM_SCSI_SELECT_TIMEOUT;
! 1823: goto disc1;
! 1824: }
! 1825: break;
! 1826:
! 1827: case TRM_COMPLETED:
! 1828: disc1:
! 1829: /*
! 1830: * TRM_COMPLETED - remove id from mask of active tags
! 1831: */
! 1832: pDCB->pActiveSRB = NULL;
! 1833: trm_FinishSRB(sc, pSRB);
! 1834: break;
! 1835:
! 1836: default:
! 1837: break;
! 1838: }
! 1839:
! 1840: trm_StartWaitingSRB(sc);
! 1841: }
! 1842:
! 1843: /*
! 1844: * ------------------------------------------------------------
! 1845: * Function : trm_Reselect
! 1846: * Purpose :
! 1847: * Inputs :
! 1848: * ------------------------------------------------------------
! 1849: */
! 1850: void
! 1851: trm_Reselect(struct trm_softc *sc)
! 1852: {
! 1853: const bus_space_handle_t ioh = sc->sc_iohandle;
! 1854: const bus_space_tag_t iot = sc->sc_iotag;
! 1855: struct trm_scsi_req_q *pSRB;
! 1856: struct trm_dcb *pDCB;
! 1857: u_int16_t RselTarLunId;
! 1858: u_int8_t target, lun;
! 1859:
! 1860: #ifdef TRM_DEBUG0
! 1861: printf("%s: trm_Reselect\n", sc->sc_device.dv_xname);
! 1862: #endif
! 1863:
! 1864: pDCB = sc->pActiveDCB;
! 1865: if (pDCB != NULL) {
! 1866: /*
! 1867: * Arbitration lost but Reselection win
! 1868: */
! 1869: pSRB = pDCB->pActiveSRB;
! 1870: trm_RewaitSRB(sc, pSRB);
! 1871: }
! 1872:
! 1873: /*
! 1874: * Read Reselected Target Id and LUN
! 1875: */
! 1876: RselTarLunId = bus_space_read_2(iot, ioh, TRM_S1040_SCSI_TARGETID) & 0x1FFF;
! 1877: /* TODO XXXX: Make endian independent! */
! 1878: target = RselTarLunId & 0xff;
! 1879: lun = (RselTarLunId >> 8) & 0xff;
! 1880:
! 1881: #ifdef TRM_DEBUG0
! 1882: printf("%s: reselect - target = %d, lun = %d\n",
! 1883: sc->sc_device.dv_xname, target, lun);
! 1884: #endif
! 1885:
! 1886: if ((target < TRM_MAX_TARGETS) && (lun < TRM_MAX_LUNS))
! 1887: pDCB = sc->pDCB[target][lun];
! 1888: else
! 1889: pDCB = NULL;
! 1890:
! 1891: if (pDCB == NULL)
! 1892: printf("%s: reselect - target = %d, lun = %d not found\n",
! 1893: sc->sc_device.dv_xname, target, lun);
! 1894:
! 1895: sc->pActiveDCB = pDCB;
! 1896:
! 1897: /* TODO XXXX: This will crash if pDCB is ever NULL */
! 1898: if ((pDCB->DCBFlag & TRM_USE_TAG_QUEUING) != 0) {
! 1899: pSRB = &sc->SRB[0];
! 1900: pDCB->pActiveSRB = pSRB;
! 1901: } else {
! 1902: pSRB = pDCB->pActiveSRB;
! 1903: if (pSRB == NULL || (pSRB->SRBState != TRM_DISCONNECTED)) {
! 1904: /*
! 1905: * abort command
! 1906: */
! 1907: pSRB = &sc->SRB[0];
! 1908: pSRB->SRBState = TRM_UNEXPECT_RESEL;
! 1909: pDCB->pActiveSRB = pSRB;
! 1910: trm_EnableMsgOut(sc, MSG_ABORT);
! 1911: } else
! 1912: pSRB->SRBState = TRM_DATA_XFER;
! 1913: }
! 1914: pSRB->ScsiPhase = PH_BUS_FREE; /* SCSI bus free Phase */
! 1915:
! 1916: /*
! 1917: * Program HA ID, target ID, period and offset
! 1918: */
! 1919: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_TARGETID, target);
! 1920: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_HOSTID, sc->sc_AdaptSCSIID);
! 1921: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_SYNC, pDCB->SyncPeriod);
! 1922: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_OFFSET, pDCB->SyncOffset);
! 1923:
! 1924: /*
! 1925: * it's important for atn stop
! 1926: */
! 1927: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL, DO_DATALATCH);
! 1928: DELAY(30);
! 1929:
! 1930: /*
! 1931: * SCSI command
! 1932: * to rls the /ACK signal
! 1933: */
! 1934: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_COMMAND, SCMD_MSGACCEPT);
! 1935: }
! 1936:
! 1937: /*
! 1938: * ------------------------------------------------------------
! 1939: * Function : trm_FinishSRB
! 1940: * Purpose : Complete execution of a SCSI command
! 1941: * Signal completion to the generic SCSI driver
! 1942: * Inputs :
! 1943: * ------------------------------------------------------------
! 1944: */
! 1945: void
! 1946: trm_FinishSRB(struct trm_softc *sc, struct trm_scsi_req_q *pSRB)
! 1947: {
! 1948: struct scsi_inquiry_data *ptr;
! 1949: struct scsi_sense_data *s1, *s2;
! 1950: struct scsi_xfer *xs = pSRB->xs;
! 1951: struct trm_dcb *pDCB = pSRB->pSRBDCB;
! 1952: int target, lun;
! 1953:
! 1954: #ifdef TRM_DEBUG0
! 1955: printf("%s: trm_FinishSRB. sc = %p, pSRB = %p\n",
! 1956: sc->sc_device.dv_xname, sc, pSRB);
! 1957: #endif
! 1958: pDCB->DCBFlag &= ~TRM_QUEUE_FULL;
! 1959:
! 1960: if (xs == NULL) {
! 1961: trm_ReleaseSRB(sc, pSRB);
! 1962: return;
! 1963: }
! 1964:
! 1965: timeout_del(&xs->stimeout);
! 1966:
! 1967: xs->status = pSRB->TargetStatus;
! 1968:
! 1969: switch (xs->status) {
! 1970: case SCSI_INTERM_COND_MET:
! 1971: case SCSI_COND_MET:
! 1972: case SCSI_INTERM:
! 1973: case SCSI_OK:
! 1974: switch (pSRB->AdaptStatus) {
! 1975: case TRM_STATUS_GOOD:
! 1976: if ((pSRB->SRBFlag & TRM_PARITY_ERROR) != 0) {
! 1977: #ifdef TRM_DEBUG0
! 1978: printf("%s: trm_FinishSRB. TRM_PARITY_ERROR\n",
! 1979: sc->sc_device.dv_xname);
! 1980: #endif
! 1981: xs->error = XS_DRIVER_STUFFUP;
! 1982:
! 1983: } else if ((pSRB->SRBFlag & TRM_SCSI_TIMED_OUT) != 0) {
! 1984: xs->error = XS_TIMEOUT;
! 1985:
! 1986: } else if ((pSRB->SRBFlag & TRM_AUTO_REQSENSE) != 0) {
! 1987: s1 = &pSRB->scsisense;
! 1988: s2 = &xs->sense;
! 1989:
! 1990: *s2 = *s1;
! 1991:
! 1992: xs->status = SCSI_CHECK;
! 1993: xs->error = XS_SENSE;
! 1994:
! 1995: } else
! 1996: xs->error = XS_NOERROR;
! 1997: break;
! 1998:
! 1999: case TRM_OVER_UNDER_RUN:
! 2000: #ifdef TRM_DEBUG0
! 2001: printf("%s: trm_FinishSRB. TRM_OVER_UNDER_RUN\n",
! 2002: sc->sc_device.dv_xname);
! 2003: #endif
! 2004: xs->error = XS_DRIVER_STUFFUP;
! 2005: break;
! 2006:
! 2007: default:
! 2008: #ifdef TRM_DEBUG0
! 2009: printf("%s: trm_FinishSRB. AdaptStatus Error = 0x%02x\n",
! 2010: sc->sc_device.dv_xname, pSRB->AdaptStatus);
! 2011: #endif
! 2012: xs->error = XS_DRIVER_STUFFUP;
! 2013: break;
! 2014: }
! 2015: break;
! 2016:
! 2017: case SCSI_TERMINATED:
! 2018: case SCSI_ACA_ACTIVE:
! 2019: case SCSI_CHECK:
! 2020: if ((pSRB->SRBFlag & TRM_AUTO_REQSENSE) != 0)
! 2021: xs->error = XS_DRIVER_STUFFUP;
! 2022: else {
! 2023: trm_RequestSense(sc, pSRB);
! 2024: return;
! 2025: }
! 2026: break;
! 2027:
! 2028: case SCSI_QUEUE_FULL:
! 2029: /* this says no more until someone completes */
! 2030: pDCB->DCBFlag |= TRM_QUEUE_FULL;
! 2031: trm_RewaitSRB(sc, pSRB);
! 2032: return;
! 2033:
! 2034: case SCSI_RESV_CONFLICT:
! 2035: case SCSI_BUSY:
! 2036: xs->error = XS_BUSY;
! 2037: break;
! 2038:
! 2039: case TRM_SCSI_UNEXP_BUS_FREE:
! 2040: xs->status = SCSI_OK;
! 2041: xs->error = XS_DRIVER_STUFFUP;
! 2042: break;
! 2043:
! 2044: case TRM_SCSI_BUS_RST_DETECTED:
! 2045: xs->status = SCSI_OK;
! 2046: xs->error = XS_RESET;
! 2047: break;
! 2048:
! 2049: case TRM_SCSI_SELECT_TIMEOUT:
! 2050: xs->status = SCSI_OK;
! 2051: xs->error = XS_SELTIMEOUT;
! 2052: break;
! 2053:
! 2054: default:
! 2055: xs->error = XS_DRIVER_STUFFUP;
! 2056: break;
! 2057: }
! 2058:
! 2059: target = xs->sc_link->target;
! 2060: lun = xs->sc_link->lun;
! 2061:
! 2062: if ((xs->flags & SCSI_POLL) != 0) {
! 2063:
! 2064: if (xs->cmd->opcode == INQUIRY) {
! 2065:
! 2066: ptr = (struct scsi_inquiry_data *) xs->data;
! 2067:
! 2068: if ((xs->error != XS_NOERROR) ||
! 2069: ((ptr->device & SID_QUAL_BAD_LU) == SID_QUAL_BAD_LU)) {
! 2070: #ifdef TRM_DEBUG0
! 2071: printf("%s: trm_FinishSRB NO Device:target= %d,lun= %d\n",
! 2072: sc->sc_device.dv_xname, target, lun);
! 2073: #endif
! 2074: free(pDCB, M_DEVBUF);
! 2075: sc->pDCB[target][lun] = NULL;
! 2076: pDCB = NULL;
! 2077:
! 2078: } else
! 2079: pDCB->sc_link = xs->sc_link;
! 2080: }
! 2081: }
! 2082:
! 2083: trm_ReleaseSRB(sc, pSRB);
! 2084:
! 2085: xs->flags |= ITSDONE;
! 2086:
! 2087: /*
! 2088: * Notify cmd done
! 2089: */
! 2090: #ifdef TRM_DEBUG0
! 2091: if ((xs->error != 0) || (xs->status != 0) || ((xs->flags & SCSI_POLL) != 0))
! 2092: printf("%s: trm_FinishSRB. %d/%d xs->cmd->opcode = 0x%02x, xs->error = %d, xs->status = %d\n",
! 2093: sc->sc_device.dv_xname, target, lun, xs->cmd->opcode, xs->error, xs->status);
! 2094: #endif
! 2095:
! 2096: scsi_done(xs);
! 2097: }
! 2098:
! 2099: /*
! 2100: * ------------------------------------------------------------
! 2101: * Function : trm_ReleaseSRB
! 2102: * Purpose :
! 2103: * Inputs :
! 2104: * ------------------------------------------------------------
! 2105: */
! 2106: void
! 2107: trm_ReleaseSRB(struct trm_softc *sc, struct trm_scsi_req_q *pSRB)
! 2108: {
! 2109: struct scsi_xfer *xs = pSRB->xs;
! 2110: int intflag;
! 2111:
! 2112: intflag = splbio();
! 2113:
! 2114: if (pSRB->TagNumber != TRM_NO_TAG) {
! 2115: pSRB->pSRBDCB->TagMask &= ~(1 << pSRB->TagNumber);
! 2116: pSRB->TagNumber = TRM_NO_TAG;
! 2117: }
! 2118:
! 2119: if (xs != NULL) {
! 2120: timeout_del(&xs->stimeout);
! 2121:
! 2122: if (xs->datalen != 0) {
! 2123: bus_dmamap_sync(sc->sc_dmatag, pSRB->dmamapxfer,
! 2124: 0, pSRB->dmamapxfer->dm_mapsize,
! 2125: (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
! 2126: BUS_DMASYNC_POSTWRITE);
! 2127: bus_dmamap_unload(sc->sc_dmatag, pSRB->dmamapxfer);
! 2128: }
! 2129: }
! 2130:
! 2131: /* SRB may have started & finished, or be waiting and timed out */
! 2132: if ((pSRB->SRBFlag & TRM_ON_WAITING_SRB) != 0) {
! 2133: pSRB->SRBFlag &= ~TRM_ON_WAITING_SRB;
! 2134: TAILQ_REMOVE(&sc->waitingSRB, pSRB, link);
! 2135: }
! 2136: if ((pSRB->SRBFlag & TRM_ON_GOING_SRB) != 0) {
! 2137: pSRB->SRBFlag &= ~TRM_ON_GOING_SRB;
! 2138: TAILQ_REMOVE(&sc->goingSRB, pSRB, link);
! 2139: }
! 2140:
! 2141: bzero(&pSRB->SegmentX[0], sizeof(pSRB->SegmentX));
! 2142: bzero(&pSRB->CmdBlock[0], sizeof(pSRB->CmdBlock));
! 2143: bzero(&pSRB->scsisense, sizeof(pSRB->scsisense));
! 2144:
! 2145: pSRB->SRBTotalXferLength = 0;
! 2146: pSRB->SRBSGCount = 0;
! 2147: pSRB->SRBSGIndex = 0;
! 2148: pSRB->SRBFlag = 0;
! 2149:
! 2150: pSRB->SRBState = TRM_FREE;
! 2151: pSRB->AdaptStatus = TRM_STATUS_GOOD;
! 2152: pSRB->TargetStatus = SCSI_OK;
! 2153: pSRB->ScsiPhase = PH_BUS_FREE; /* SCSI bus free Phase */
! 2154:
! 2155: pSRB->xs = NULL;
! 2156: pSRB->pSRBDCB = NULL;
! 2157:
! 2158: if (pSRB != &sc->SRB[0])
! 2159: TAILQ_INSERT_TAIL(&sc->freeSRB, pSRB, link);
! 2160:
! 2161: splx(intflag);
! 2162: }
! 2163:
! 2164: /*
! 2165: * ------------------------------------------------------------
! 2166: * Function : trm_GoingSRB_Done
! 2167: * Purpose :
! 2168: * Inputs :
! 2169: * ------------------------------------------------------------
! 2170: */
! 2171: void
! 2172: trm_GoingSRB_Done(struct trm_softc *sc)
! 2173: {
! 2174: struct trm_scsi_req_q *pSRB;
! 2175:
! 2176: /* ASSUME we are inside a splbio()/splx() pair */
! 2177:
! 2178: while ((pSRB = TAILQ_FIRST(&sc->goingSRB)) != NULL) {
! 2179: /* TODO XXXX: Is TIMED_OUT the best status? */
! 2180: pSRB->SRBFlag |= TRM_SCSI_TIMED_OUT;
! 2181: trm_FinishSRB(sc, pSRB);
! 2182: }
! 2183: }
! 2184:
! 2185: /*
! 2186: * ------------------------------------------------------------
! 2187: * Function : trm_ResetSCSIBus
! 2188: * Purpose : Reset the SCSI bus
! 2189: * Inputs : struct trm_softc * -
! 2190: * ------------------------------------------------------------
! 2191: */
! 2192: void
! 2193: trm_ResetSCSIBus(struct trm_softc *sc)
! 2194: {
! 2195: const bus_space_handle_t ioh = sc->sc_iohandle;
! 2196: const bus_space_tag_t iot = sc->sc_iotag;
! 2197: int intflag;
! 2198:
! 2199: intflag = splbio();
! 2200:
! 2201: sc->sc_Flag |= RESET_DEV;
! 2202:
! 2203: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL, DO_RSTSCSI);
! 2204: while ((bus_space_read_2(iot, ioh,
! 2205: TRM_S1040_SCSI_INTSTATUS) & INT_SCSIRESET) == 0);
! 2206:
! 2207: splx(intflag);
! 2208: }
! 2209:
! 2210: /*
! 2211: * ------------------------------------------------------------
! 2212: * Function : trm_ScsiRstDetect
! 2213: * Purpose :
! 2214: * Inputs :
! 2215: * ------------------------------------------------------------
! 2216: */
! 2217: void
! 2218: trm_ScsiRstDetect(struct trm_softc *sc)
! 2219: {
! 2220: const bus_space_handle_t ioh = sc->sc_iohandle;
! 2221: const bus_space_tag_t iot = sc->sc_iotag;
! 2222: int wlval;
! 2223:
! 2224: #ifdef TRM_DEBUG0
! 2225: printf("%s: trm_ScsiRstDetect\n", sc->sc_device.dv_xname);
! 2226: #endif
! 2227:
! 2228: wlval = 1000;
! 2229: /*
! 2230: * delay 1 sec
! 2231: */
! 2232: while (--wlval != 0)
! 2233: DELAY(1000);
! 2234:
! 2235: bus_space_write_1(iot, ioh, TRM_S1040_DMA_CONTROL, STOPDMAXFER);
! 2236: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL, DO_CLRFIFO);
! 2237:
! 2238: if ((sc->sc_Flag & RESET_DEV) != 0)
! 2239: sc->sc_Flag |= RESET_DONE;
! 2240: else {
! 2241: sc->sc_Flag |= RESET_DETECT;
! 2242: trm_ResetAllDevParam(sc);
! 2243: trm_RecoverSRB(sc);
! 2244: sc->pActiveDCB = NULL;
! 2245: sc->sc_Flag = 0;
! 2246: trm_StartWaitingSRB(sc);
! 2247: }
! 2248: }
! 2249:
! 2250: /*
! 2251: * ------------------------------------------------------------
! 2252: * Function : trm_RequestSense
! 2253: * Purpose :
! 2254: * Inputs :
! 2255: * ------------------------------------------------------------
! 2256: */
! 2257: void
! 2258: trm_RequestSense(struct trm_softc *sc, struct trm_scsi_req_q *pSRB)
! 2259: {
! 2260: pSRB->SRBFlag |= TRM_AUTO_REQSENSE;
! 2261:
! 2262: /*
! 2263: * Status of initiator/target
! 2264: */
! 2265: pSRB->AdaptStatus = TRM_STATUS_GOOD;
! 2266: pSRB->TargetStatus = SCSI_OK;
! 2267: /*
! 2268: * Status of initiator/target
! 2269: */
! 2270:
! 2271: pSRB->SegmentX[0].address = pSRB->scsisensePhyAddr;
! 2272: pSRB->SegmentX[0].length = sizeof(struct scsi_sense_data);
! 2273: pSRB->SRBTotalXferLength = sizeof(struct scsi_sense_data);
! 2274: pSRB->SRBSGCount = 1;
! 2275: pSRB->SRBSGIndex = 0;
! 2276:
! 2277: bzero(&pSRB->CmdBlock[0], sizeof(pSRB->CmdBlock));
! 2278:
! 2279: pSRB->CmdBlock[0] = REQUEST_SENSE;
! 2280: pSRB->CmdBlock[1] = (pSRB->xs->sc_link->lun) << 5;
! 2281: pSRB->CmdBlock[4] = sizeof(struct scsi_sense_data);
! 2282:
! 2283: pSRB->ScsiCmdLen = 6;
! 2284:
! 2285: if ((pSRB->xs != NULL) && ((pSRB->xs->flags & SCSI_POLL) == 0))
! 2286: timeout_add(&pSRB->xs->stimeout, (pSRB->xs->timeout/1000) * hz);
! 2287:
! 2288: if (trm_StartSRB(sc, pSRB) != 0)
! 2289: trm_RewaitSRB(sc, pSRB);
! 2290: }
! 2291:
! 2292: /*
! 2293: * ------------------------------------------------------------
! 2294: * Function : trm_EnableMsgOut
! 2295: * Purpose : set up MsgBuf to send out a single byte message
! 2296: * Inputs :
! 2297: * ------------------------------------------------------------
! 2298: */
! 2299: void
! 2300: trm_EnableMsgOut(struct trm_softc *sc, u_int8_t msg)
! 2301: {
! 2302: sc->MsgBuf[0] = msg;
! 2303: sc->MsgCnt = 1;
! 2304:
! 2305: bus_space_write_2(sc->sc_iotag, sc->sc_iohandle, TRM_S1040_SCSI_CONTROL, DO_SETATN);
! 2306: }
! 2307:
! 2308: /*
! 2309: * ------------------------------------------------------------
! 2310: * Function : trm_linkSRB
! 2311: * Purpose :
! 2312: * Inputs :
! 2313: * ------------------------------------------------------------
! 2314: */
! 2315: void
! 2316: trm_linkSRB(struct trm_softc *sc)
! 2317: {
! 2318: struct trm_scsi_req_q *pSRB;
! 2319: int i, intflag;
! 2320:
! 2321: intflag = splbio();
! 2322:
! 2323: for (i = 0; i < TRM_MAX_SRB_CNT; i++) {
! 2324: pSRB = &sc->SRB[i];
! 2325:
! 2326: pSRB->PhysSRB = sc->sc_dmamap_control->dm_segs[0].ds_addr
! 2327: + i * sizeof(struct trm_scsi_req_q);
! 2328:
! 2329: pSRB->SRBSGPhyAddr = sc->sc_dmamap_control->dm_segs[0].ds_addr
! 2330: + i * sizeof(struct trm_scsi_req_q)
! 2331: + offsetof(struct trm_scsi_req_q, SegmentX);
! 2332:
! 2333: pSRB->scsisensePhyAddr = sc->sc_dmamap_control->dm_segs[0].ds_addr
! 2334: + i * sizeof(struct trm_scsi_req_q)
! 2335: + offsetof(struct trm_scsi_req_q, scsisense);
! 2336:
! 2337: /*
! 2338: * map all SRB space
! 2339: */
! 2340: if (bus_dmamap_create(sc->sc_dmatag, TRM_MAX_PHYSG_BYTE,
! 2341: TRM_MAX_SG_LISTENTRY, TRM_MAX_PHYSG_BYTE, 0,
! 2342: BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
! 2343: &pSRB->dmamapxfer) != 0) {
! 2344: printf("%s: unable to create DMA transfer map\n",
! 2345: sc->sc_device.dv_xname);
! 2346: splx(intflag);
! 2347: return;
! 2348: }
! 2349:
! 2350: if (i > 0)
! 2351: /* We use sc->SRB[0] directly, so *don't* link it */
! 2352: TAILQ_INSERT_TAIL(&sc->freeSRB, pSRB, link);
! 2353: #ifdef TRM_DEBUG0
! 2354: printf("pSRB = %p ", pSRB);
! 2355: #endif
! 2356: }
! 2357: #ifdef TRM_DEBUG0
! 2358: printf("\n ");
! 2359: #endif
! 2360: splx(intflag);
! 2361: }
! 2362:
! 2363: /*
! 2364: * ------------------------------------------------------------
! 2365: * Function : trm_minphys
! 2366: * Purpose : limited by the number of segments in the dma segment list
! 2367: * Inputs : *buf
! 2368: * ------------------------------------------------------------
! 2369: */
! 2370: void
! 2371: trm_minphys(struct buf *bp)
! 2372: {
! 2373: if (bp->b_bcount > (TRM_MAX_SG_LISTENTRY-1) * (long) NBPG) {
! 2374: bp->b_bcount = (TRM_MAX_SG_LISTENTRY-1) * (long) NBPG;
! 2375: }
! 2376: minphys(bp);
! 2377: }
! 2378:
! 2379: /*
! 2380: * ------------------------------------------------------------
! 2381: * Function : trm_initACB
! 2382: * Purpose : initialize the internal structures for a given SCSI host
! 2383: * Inputs :
! 2384: * ------------------------------------------------------------
! 2385: */
! 2386: void
! 2387: trm_initACB(struct trm_softc *sc, int unit)
! 2388: {
! 2389: const bus_space_handle_t ioh = sc->sc_iohandle;
! 2390: const bus_space_tag_t iot = sc->sc_iotag;
! 2391: struct trm_adapter_nvram *pEEpromBuf;
! 2392: struct trm_dcb *pDCB;
! 2393: int target, lun;
! 2394:
! 2395: pEEpromBuf = &trm_eepromBuf[unit];
! 2396: sc->sc_config = HCC_AUTOTERM | HCC_PARITY;
! 2397:
! 2398: if ((bus_space_read_1(iot, ioh, TRM_S1040_GEN_STATUS) & WIDESCSI) != 0)
! 2399: sc->sc_config |= HCC_WIDE_CARD;
! 2400:
! 2401: if ((pEEpromBuf->NvramChannelCfg & NAC_POWERON_SCSI_RESET) != 0)
! 2402: sc->sc_config |= HCC_SCSI_RESET;
! 2403:
! 2404: TAILQ_INIT(&sc->freeSRB);
! 2405: TAILQ_INIT(&sc->waitingSRB);
! 2406: TAILQ_INIT(&sc->goingSRB);
! 2407:
! 2408: sc->pActiveDCB = NULL;
! 2409: sc->sc_AdapterUnit = unit;
! 2410: sc->sc_AdaptSCSIID = pEEpromBuf->NvramScsiId;
! 2411: sc->sc_TagMaxNum = 2 << pEEpromBuf->NvramMaxTag;
! 2412: sc->sc_Flag = 0;
! 2413:
! 2414: /*
! 2415: * put all SRB's (except [0]) onto the freeSRB list
! 2416: */
! 2417: trm_linkSRB(sc);
! 2418:
! 2419: /*
! 2420: * allocate DCB array
! 2421: */
! 2422: for (target = 0; target < TRM_MAX_TARGETS; target++) {
! 2423: if (target == sc->sc_AdaptSCSIID)
! 2424: continue;
! 2425:
! 2426: for (lun = 0; lun < TRM_MAX_LUNS; lun++) {
! 2427: pDCB = (struct trm_dcb *)malloc(sizeof(struct trm_dcb), M_DEVBUF, M_NOWAIT);
! 2428: sc->pDCB[target][lun] = pDCB;
! 2429:
! 2430: if (pDCB == NULL)
! 2431: continue;
! 2432:
! 2433: bzero(pDCB, sizeof(struct trm_dcb));
! 2434:
! 2435: pDCB->target = target;
! 2436: pDCB->lun = lun;
! 2437: pDCB->pActiveSRB = NULL;
! 2438: }
! 2439: }
! 2440:
! 2441: sc->sc_adapter.scsi_cmd = trm_scsi_cmd;
! 2442: sc->sc_adapter.scsi_minphys = trm_minphys;
! 2443:
! 2444: sc->sc_link.adapter_softc = sc;
! 2445: sc->sc_link.adapter_target = sc->sc_AdaptSCSIID;
! 2446: sc->sc_link.openings = 30; /* So TagMask (32 bit integer) always has space */
! 2447: sc->sc_link.device = &trm_device;
! 2448: sc->sc_link.adapter = &sc->sc_adapter;
! 2449: sc->sc_link.adapter_buswidth = ((sc->sc_config & HCC_WIDE_CARD) == 0) ? 8:16;
! 2450:
! 2451: trm_reset(sc);
! 2452: }
! 2453:
! 2454: /*
! 2455: * ------------------------------------------------------------
! 2456: * Function : trm_write_all
! 2457: * Description : write pEEpromBuf 128 bytes to seeprom
! 2458: * Input : iot, ioh - chip's base address
! 2459: * Output : none
! 2460: * ------------------------------------------------------------
! 2461: */
! 2462: void
! 2463: trm_write_all(struct trm_adapter_nvram *pEEpromBuf, bus_space_tag_t iot,
! 2464: bus_space_handle_t ioh)
! 2465: {
! 2466: u_int8_t *bpEeprom = (u_int8_t *)pEEpromBuf;
! 2467: u_int8_t bAddr;
! 2468:
! 2469: /*
! 2470: * Enable SEEPROM
! 2471: */
! 2472: bus_space_write_1(iot, ioh, TRM_S1040_GEN_CONTROL,
! 2473: (bus_space_read_1(iot, ioh, TRM_S1040_GEN_CONTROL) | EN_EEPROM));
! 2474: /*
! 2475: * Write enable
! 2476: */
! 2477: trm_write_cmd(iot, ioh, 0x04, 0xFF);
! 2478: bus_space_write_1(iot, ioh, TRM_S1040_GEN_NVRAM, 0);
! 2479: trm_wait_30us(iot, ioh);
! 2480: for (bAddr = 0; bAddr < 128; bAddr++, bpEeprom++)
! 2481: trm_set_data(iot, ioh, bAddr, *bpEeprom);
! 2482: /*
! 2483: * Write disable
! 2484: */
! 2485: trm_write_cmd(iot, ioh, 0x04, 0x00);
! 2486: bus_space_write_1(iot, ioh, TRM_S1040_GEN_NVRAM, 0);
! 2487: trm_wait_30us(iot, ioh);
! 2488: /*
! 2489: * Disable SEEPROM
! 2490: */
! 2491: bus_space_write_1(iot, ioh, TRM_S1040_GEN_CONTROL,
! 2492: (bus_space_read_1(iot, ioh, TRM_S1040_GEN_CONTROL) & ~EN_EEPROM));
! 2493: }
! 2494:
! 2495: /*
! 2496: * ------------------------------------------------------------
! 2497: * Function : trm_set_data
! 2498: * Description : write one byte to seeprom
! 2499: * Input : iot, ioh - chip's base address
! 2500: * bAddr - address of SEEPROM
! 2501: * bData - data of SEEPROM
! 2502: * Output : none
! 2503: * ------------------------------------------------------------
! 2504: */
! 2505: void
! 2506: trm_set_data(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t bAddr,
! 2507: u_int8_t bData)
! 2508: {
! 2509: u_int8_t bSendData;
! 2510: int i;
! 2511:
! 2512: /*
! 2513: * Send write command & address
! 2514: */
! 2515: trm_write_cmd(iot, ioh, 0x05, bAddr);
! 2516: /*
! 2517: * Write data
! 2518: */
! 2519: for (i = 0; i < 8; i++, bData <<= 1) {
! 2520: bSendData = NVR_SELECT;
! 2521: if ((bData & 0x80) != 0) { /* Start from bit 7 */
! 2522: bSendData |= NVR_BITOUT;
! 2523: }
! 2524: bus_space_write_1(iot, ioh, TRM_S1040_GEN_NVRAM, bSendData);
! 2525: trm_wait_30us(iot, ioh);
! 2526: bus_space_write_1(iot, ioh, TRM_S1040_GEN_NVRAM,
! 2527: (bSendData | NVR_CLOCK));
! 2528: trm_wait_30us(iot, ioh);
! 2529: }
! 2530: bus_space_write_1(iot, ioh, TRM_S1040_GEN_NVRAM, NVR_SELECT);
! 2531: trm_wait_30us(iot, ioh);
! 2532: /*
! 2533: * Disable chip select
! 2534: */
! 2535: bus_space_write_1(iot, ioh, TRM_S1040_GEN_NVRAM, 0);
! 2536: trm_wait_30us(iot, ioh);
! 2537: bus_space_write_1(iot, ioh, TRM_S1040_GEN_NVRAM, NVR_SELECT);
! 2538: trm_wait_30us(iot, ioh);
! 2539: /*
! 2540: * Wait for write ready
! 2541: */
! 2542: for (;;) {
! 2543: bus_space_write_1(iot, ioh, TRM_S1040_GEN_NVRAM,
! 2544: (NVR_SELECT | NVR_CLOCK));
! 2545: trm_wait_30us(iot, ioh);
! 2546: bus_space_write_1(iot, ioh, TRM_S1040_GEN_NVRAM, NVR_SELECT);
! 2547: trm_wait_30us(iot, ioh);
! 2548: if (bus_space_read_1(iot, ioh, TRM_S1040_GEN_NVRAM) & NVR_BITIN)
! 2549: break;
! 2550: }
! 2551: /*
! 2552: * Disable chip select
! 2553: */
! 2554: bus_space_write_1(iot, ioh, TRM_S1040_GEN_NVRAM, 0);
! 2555: }
! 2556:
! 2557: /*
! 2558: * ------------------------------------------------------------
! 2559: * Function : trm_read_all
! 2560: * Description : read seeprom 128 bytes to pEEpromBuf
! 2561: * Input : pEEpromBuf, iot, ioh - chip's base address
! 2562: * Output : none
! 2563: * ------------------------------------------------------------
! 2564: */
! 2565: void
! 2566: trm_read_all(struct trm_adapter_nvram *pEEpromBuf, bus_space_tag_t iot,
! 2567: bus_space_handle_t ioh)
! 2568: {
! 2569: u_int8_t *bpEeprom = (u_int8_t *)pEEpromBuf;
! 2570: u_int8_t bAddr;
! 2571:
! 2572: /*
! 2573: * Enable SEEPROM
! 2574: */
! 2575: bus_space_write_1(iot, ioh, TRM_S1040_GEN_CONTROL,
! 2576: (bus_space_read_1(iot, ioh, TRM_S1040_GEN_CONTROL) | EN_EEPROM));
! 2577:
! 2578: for (bAddr = 0; bAddr < 128; bAddr++, bpEeprom++)
! 2579: *bpEeprom = trm_get_data(iot, ioh, bAddr);
! 2580:
! 2581: /*
! 2582: * Disable SEEPROM
! 2583: */
! 2584: bus_space_write_1(iot, ioh, TRM_S1040_GEN_CONTROL,
! 2585: (bus_space_read_1(iot, ioh, TRM_S1040_GEN_CONTROL) & ~EN_EEPROM));
! 2586: }
! 2587:
! 2588: /*
! 2589: * ------------------------------------------------------------
! 2590: * Function : trm_get_data
! 2591: * Description : read one byte from seeprom
! 2592: * Input : iot, ioh - chip's base address
! 2593: * bAddr - address of SEEPROM
! 2594: * Output : bData - data of SEEPROM
! 2595: * ------------------------------------------------------------
! 2596: */
! 2597: u_int8_t
! 2598: trm_get_data( bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t bAddr)
! 2599: {
! 2600: u_int8_t bReadData, bData;
! 2601: int i;
! 2602:
! 2603: bData = 0;
! 2604:
! 2605: /*
! 2606: * Send read command & address
! 2607: */
! 2608: trm_write_cmd(iot, ioh, 0x06, bAddr);
! 2609:
! 2610: for (i = 0; i < 8; i++) {
! 2611: /*
! 2612: * Read data
! 2613: */
! 2614: bus_space_write_1(iot, ioh, TRM_S1040_GEN_NVRAM,
! 2615: (NVR_SELECT | NVR_CLOCK));
! 2616: trm_wait_30us(iot, ioh);
! 2617: bus_space_write_1(iot, ioh, TRM_S1040_GEN_NVRAM, NVR_SELECT);
! 2618: /*
! 2619: * Get data bit while falling edge
! 2620: */
! 2621: bReadData = bus_space_read_1(iot, ioh, TRM_S1040_GEN_NVRAM);
! 2622: bData <<= 1;
! 2623: if ((bReadData & NVR_BITIN) != 0)
! 2624: bData |= 1;
! 2625: trm_wait_30us(iot, ioh);
! 2626: }
! 2627: /*
! 2628: * Disable chip select
! 2629: */
! 2630: bus_space_write_1(iot, ioh, TRM_S1040_GEN_NVRAM, 0);
! 2631:
! 2632: return bData;
! 2633: }
! 2634:
! 2635: /*
! 2636: * ------------------------------------------------------------
! 2637: * Function : trm_wait_30us
! 2638: * Description : wait 30 us
! 2639: * Input : iot, ioh - chip's base address
! 2640: * Output : none
! 2641: * ------------------------------------------------------------
! 2642: */
! 2643: void
! 2644: trm_wait_30us(bus_space_tag_t iot, bus_space_handle_t ioh)
! 2645: {
! 2646: bus_space_write_1(iot, ioh, TRM_S1040_GEN_TIMER, 5);
! 2647:
! 2648: while ((bus_space_read_1(iot, ioh, TRM_S1040_GEN_STATUS) & GTIMEOUT)
! 2649: == 0);
! 2650: }
! 2651:
! 2652: /*
! 2653: * ------------------------------------------------------------
! 2654: * Function : trm_write_cmd
! 2655: * Description : write SB and Op Code into seeprom
! 2656: * Input : iot, ioh - chip's base address
! 2657: * bCmd - SB + Op Code
! 2658: * bAddr - address of SEEPROM
! 2659: * Output : none
! 2660: * ------------------------------------------------------------
! 2661: */
! 2662: void
! 2663: trm_write_cmd( bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t bCmd,
! 2664: u_int8_t bAddr)
! 2665: {
! 2666: u_int8_t bSendData;
! 2667: int i;
! 2668:
! 2669: for (i = 0; i < 3; i++, bCmd <<= 1) {
! 2670: /*
! 2671: * Program SB + OP code
! 2672: */
! 2673: bSendData = NVR_SELECT;
! 2674: if (bCmd & 0x04) /* Start from bit 2 */
! 2675: bSendData |= NVR_BITOUT;
! 2676: bus_space_write_1(iot, ioh, TRM_S1040_GEN_NVRAM, bSendData);
! 2677: trm_wait_30us(iot, ioh);
! 2678: bus_space_write_1(iot, ioh, TRM_S1040_GEN_NVRAM,
! 2679: (bSendData | NVR_CLOCK));
! 2680: trm_wait_30us(iot, ioh);
! 2681: }
! 2682:
! 2683: for (i = 0; i < 7; i++, bAddr <<= 1) {
! 2684: /*
! 2685: * Program address
! 2686: */
! 2687: bSendData = NVR_SELECT;
! 2688: if (bAddr & 0x40) { /* Start from bit 6 */
! 2689: bSendData |= NVR_BITOUT;
! 2690: }
! 2691: bus_space_write_1(iot, ioh, TRM_S1040_GEN_NVRAM, bSendData);
! 2692: trm_wait_30us(iot, ioh);
! 2693: bus_space_write_1(iot, ioh, TRM_S1040_GEN_NVRAM,
! 2694: (bSendData | NVR_CLOCK));
! 2695: trm_wait_30us(iot, ioh);
! 2696: }
! 2697: bus_space_write_1(iot, ioh, TRM_S1040_GEN_NVRAM, NVR_SELECT);
! 2698: trm_wait_30us(iot, ioh);
! 2699: }
! 2700:
! 2701: /*
! 2702: * ------------------------------------------------------------
! 2703: * Function : trm_check_eeprom
! 2704: * Description : read eeprom 128 bytes to pEEpromBuf and check
! 2705: * checksum. If it is wrong, updated with default value.
! 2706: * Input : eeprom, iot, ioh - chip's base address
! 2707: * Output : none
! 2708: * ------------------------------------------------------------
! 2709: */
! 2710: void
! 2711: trm_check_eeprom(struct trm_adapter_nvram *pEEpromBuf, bus_space_tag_t iot,
! 2712: bus_space_handle_t ioh)
! 2713: {
! 2714: u_int32_t *dpEeprom = (u_int32_t *)pEEpromBuf->NvramTarget;
! 2715: u_int32_t dAddr;
! 2716: u_int16_t *wpEeprom = (u_int16_t *)pEEpromBuf;
! 2717: u_int16_t wAddr, wCheckSum;
! 2718:
! 2719: #ifdef TRM_DEBUG0
! 2720: printf("\ntrm_check_eeprom\n");
! 2721: #endif
! 2722: trm_read_all(pEEpromBuf, iot, ioh);
! 2723: wCheckSum = 0;
! 2724: for (wAddr = 0; wAddr < 64; wAddr++, wpEeprom++)
! 2725: wCheckSum += *wpEeprom;
! 2726:
! 2727: if (wCheckSum != 0x1234) {
! 2728: #ifdef TRM_DEBUG0
! 2729: printf("TRM_S1040 EEPROM Check Sum ERROR (load default)\n");
! 2730: #endif
! 2731: /*
! 2732: * Checksum error, load default
! 2733: */
! 2734: pEEpromBuf->NvramSubVendorID[0] = (u_int8_t)PCI_VENDOR_TEKRAM2;
! 2735: pEEpromBuf->NvramSubVendorID[1] = (u_int8_t)(PCI_VENDOR_TEKRAM2
! 2736: >> 8);
! 2737: pEEpromBuf->NvramSubSysID[0] = (u_int8_t)
! 2738: PCI_PRODUCT_TEKRAM2_DC3X5U;
! 2739: pEEpromBuf->NvramSubSysID[1] = (u_int8_t)
! 2740: (PCI_PRODUCT_TEKRAM2_DC3X5U >> 8);
! 2741: pEEpromBuf->NvramSubClass = 0;
! 2742: pEEpromBuf->NvramVendorID[0] = (u_int8_t)PCI_VENDOR_TEKRAM2;
! 2743: pEEpromBuf->NvramVendorID[1] = (u_int8_t)(PCI_VENDOR_TEKRAM2
! 2744: >> 8);
! 2745: pEEpromBuf->NvramDeviceID[0] = (u_int8_t)
! 2746: PCI_PRODUCT_TEKRAM2_DC3X5U;
! 2747: pEEpromBuf->NvramDeviceID[1] = (u_int8_t)
! 2748: (PCI_PRODUCT_TEKRAM2_DC3X5U >> 8);
! 2749: pEEpromBuf->NvramReserved = 0;
! 2750:
! 2751: for (dAddr = 0; dAddr < 16; dAddr++, dpEeprom++)
! 2752: /*
! 2753: * NvmTarCfg3,NvmTarCfg2,NvmTarPeriod,NvmTarCfg0
! 2754: */
! 2755: *dpEeprom = 0x00000077;
! 2756:
! 2757: /*
! 2758: * NvramMaxTag,NvramDelayTime,NvramChannelCfg,NvramScsiId
! 2759: */
! 2760: *dpEeprom++ = 0x04000F07;
! 2761:
! 2762: /*
! 2763: * NvramReserved1,NvramBootLun,NvramBootTarget,NvramReserved0
! 2764: */
! 2765: *dpEeprom++ = 0x00000015;
! 2766: for (dAddr = 0; dAddr < 12; dAddr++, dpEeprom++)
! 2767: *dpEeprom = 0;
! 2768:
! 2769: pEEpromBuf->NvramCheckSum = 0;
! 2770: for (wAddr = 0, wCheckSum =0; wAddr < 63; wAddr++, wpEeprom++)
! 2771: wCheckSum += *wpEeprom;
! 2772:
! 2773: *wpEeprom = 0x1234 - wCheckSum;
! 2774: trm_write_all(pEEpromBuf, iot, ioh);
! 2775: }
! 2776: }
! 2777:
! 2778: /*
! 2779: * ------------------------------------------------------------
! 2780: * Function : trm_initAdapter
! 2781: * Purpose : initialize the SCSI chip ctrl registers
! 2782: * Inputs : psh - pointer to this host adapter's structure
! 2783: * ------------------------------------------------------------
! 2784: */
! 2785: void
! 2786: trm_initAdapter(struct trm_softc *sc)
! 2787: {
! 2788: const bus_space_handle_t ioh = sc->sc_iohandle;
! 2789: const bus_space_tag_t iot = sc->sc_iotag;
! 2790: u_int16_t wval;
! 2791: u_int8_t bval;
! 2792:
! 2793: /*
! 2794: * program configuration 0
! 2795: */
! 2796: if ((sc->sc_config & HCC_PARITY) != 0) {
! 2797: bval = PHASELATCH | INITIATOR | BLOCKRST | PARITYCHECK;
! 2798: } else {
! 2799: bval = PHASELATCH | INITIATOR | BLOCKRST;
! 2800: }
! 2801: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_CONFIG0, bval);
! 2802: /*
! 2803: * program configuration 1
! 2804: */
! 2805: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_CONFIG1, 0x13);
! 2806: /*
! 2807: * 250ms selection timeout
! 2808: */
! 2809: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_TIMEOUT, TRM_SEL_TIMEOUT);
! 2810: /*
! 2811: * Mask all the interrupt
! 2812: */
! 2813: bus_space_write_1(iot, ioh, TRM_S1040_DMA_INTEN, 0);
! 2814: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_INTEN, 0);
! 2815: /*
! 2816: * Reset SCSI module
! 2817: */
! 2818: bus_space_write_2(iot, ioh, TRM_S1040_SCSI_CONTROL, DO_RSTMODULE);
! 2819: /*
! 2820: * program Host ID
! 2821: */
! 2822: bval = sc->sc_AdaptSCSIID;
! 2823: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_HOSTID, bval);
! 2824: /*
! 2825: * set ansynchronous transfer
! 2826: */
! 2827: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_OFFSET, 0);
! 2828: /*
! 2829: * Turn LED control off
! 2830: */
! 2831: wval = bus_space_read_2(iot, ioh, TRM_S1040_GEN_CONTROL) & 0x7F;
! 2832: bus_space_write_2(iot, ioh, TRM_S1040_GEN_CONTROL, wval);
! 2833: /*
! 2834: * DMA config
! 2835: */
! 2836: wval = bus_space_read_2(iot, ioh, TRM_S1040_DMA_CONFIG) | DMA_ENHANCE;
! 2837: bus_space_write_2(iot, ioh, TRM_S1040_DMA_CONFIG, wval);
! 2838: /*
! 2839: * Clear pending interrupt status
! 2840: */
! 2841: bus_space_read_1(iot, ioh, TRM_S1040_SCSI_INTSTATUS);
! 2842: /*
! 2843: * Enable SCSI interrupts
! 2844: */
! 2845: bus_space_write_1(iot, ioh, TRM_S1040_SCSI_INTEN,
! 2846: (EN_SELECT | EN_SELTIMEOUT | EN_DISCONNECT | EN_RESELECTED |
! 2847: EN_SCSIRESET | EN_BUSSERVICE | EN_CMDDONE));
! 2848: bus_space_write_1(iot, ioh, TRM_S1040_DMA_INTEN, EN_SCSIINTR);
! 2849: }
! 2850:
! 2851: /*
! 2852: * ------------------------------------------------------------
! 2853: * Function : trm_init
! 2854: * Purpose : initialize the internal structures for a given SCSI host
! 2855: * Inputs : host - pointer to this host adapter's structure
! 2856: * Preconditions : when this function is called, the chip_type field of
! 2857: * the ACB structure MUST have been set.
! 2858: * ------------------------------------------------------------
! 2859: */
! 2860: int
! 2861: trm_init(struct trm_softc *sc, int unit)
! 2862: {
! 2863: const bus_space_handle_t ioh = sc->sc_iohandle;
! 2864: const bus_space_tag_t iot = sc->sc_iotag;
! 2865: bus_dma_segment_t seg;
! 2866: int error, rseg, all_srbs_size;
! 2867:
! 2868: /*
! 2869: * EEPROM CHECKSUM
! 2870: */
! 2871: trm_check_eeprom(&trm_eepromBuf[unit], iot, ioh);
! 2872:
! 2873: /*
! 2874: * MEMORY ALLOCATE FOR ADAPTER CONTROL BLOCK
! 2875: */
! 2876: /*
! 2877: * allocate the space for all SCSI control blocks (SRB) for DMA memory.
! 2878: */
! 2879: all_srbs_size = TRM_MAX_SRB_CNT * sizeof(struct trm_scsi_req_q);
! 2880:
! 2881: error = bus_dmamem_alloc(sc->sc_dmatag, all_srbs_size, NBPG, 0, &seg,
! 2882: 1, &rseg, BUS_DMA_NOWAIT);
! 2883: if (error != 0) {
! 2884: printf("%s: unable to allocate SCSI REQUEST BLOCKS, error = %d\n",
! 2885: sc->sc_device.dv_xname, error);
! 2886: /*errx(error, "%s: unable to allocate SCSI request blocks",
! 2887: sc->sc_device.dv_xname);*/
! 2888: return -1;
! 2889: }
! 2890:
! 2891: error = bus_dmamem_map(sc->sc_dmatag, &seg, rseg, all_srbs_size,
! 2892: (caddr_t *)&sc->SRB, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
! 2893: if (error != 0) {
! 2894: printf("%s: unable to map SCSI REQUEST BLOCKS, error = %d\n",
! 2895: sc->sc_device.dv_xname, error);
! 2896: /*errx(error, "unable to map SCSI request blocks");*/
! 2897: return -1;
! 2898: }
! 2899:
! 2900: error = bus_dmamap_create(sc->sc_dmatag, all_srbs_size, 1,
! 2901: all_srbs_size, 0, BUS_DMA_NOWAIT,&sc->sc_dmamap_control);
! 2902: if (error != 0) {
! 2903: printf("%s: unable to create SRB DMA maps, error = %d\n",
! 2904: sc->sc_device.dv_xname, error);
! 2905: /*errx(error, "unable to create SRB DMA maps");*/
! 2906: return -1;
! 2907: }
! 2908:
! 2909: error = bus_dmamap_load(sc->sc_dmatag, sc->sc_dmamap_control,
! 2910: sc->SRB, all_srbs_size, NULL, BUS_DMA_NOWAIT);
! 2911: if (error != 0) {
! 2912: printf("%s: unable to load SRB DMA maps, error = %d\n",
! 2913: sc->sc_device.dv_xname, error);
! 2914: /*errx(error, "unable to load SRB DMA maps");*/
! 2915: return -1;
! 2916: }
! 2917: #ifdef TRM_DEBUG0
! 2918: printf("\n\n%s: all_srbs_size=%x\n",
! 2919: sc->sc_device.dv_xname, all_srbs_size);
! 2920: #endif
! 2921: bzero(sc->SRB, all_srbs_size);
! 2922: trm_initACB(sc, unit);
! 2923: trm_initAdapter(sc);
! 2924:
! 2925: return 0;
! 2926: }
! 2927:
! 2928: /* ------------------------------------------------------------
! 2929: * Function : trm_print_info
! 2930: * Purpose : Print the DCB negotiation information
! 2931: * Inputs :
! 2932: * ------------------------------------------------------------
! 2933: */
! 2934: void
! 2935: trm_print_info(struct trm_softc *sc, struct trm_dcb *pDCB)
! 2936: {
! 2937: int syncXfer, index;
! 2938:
! 2939: index = pDCB->SyncPeriod & ~(WIDE_SYNC | ALT_SYNC);
! 2940:
! 2941: printf("%s: target %d using ", sc->sc_device.dv_xname, pDCB->target);
! 2942: if ((pDCB->SyncPeriod & WIDE_SYNC) != 0)
! 2943: printf("16 bit ");
! 2944: else
! 2945: printf("8 bit ");
! 2946:
! 2947: if (pDCB->SyncOffset == 0)
! 2948: printf("Asynchronous ");
! 2949: else {
! 2950: syncXfer = 100000 / (trm_clock_period[index] * 4);
! 2951: printf("%d.%01d MHz, Offset %d ",
! 2952: syncXfer / 100, syncXfer % 100, pDCB->SyncOffset);
! 2953: }
! 2954: printf("data transfers ");
! 2955:
! 2956: if ((pDCB->DCBFlag & TRM_USE_TAG_QUEUING) != 0)
! 2957: printf("with Tag Queuing");
! 2958:
! 2959: printf("\n");
! 2960: }
CVSweb