Annotation of sys/dev/ic/iha.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: iha.c,v 1.26 2007/04/10 17:47:55 miod Exp $ */
! 2: /*-------------------------------------------------------------------------
! 3: *
! 4: * Device driver for the INI-9XXXU/UW or INIC-940/950 PCI SCSI Controller.
! 5: *
! 6: * Written for 386bsd and FreeBSD by
! 7: * Winston Hung <winstonh@initio.com>
! 8: *
! 9: * Copyright (c) 1997-1999 Initio Corp
! 10: * Copyright (c) 2000-2002 Ken Westerback
! 11: *
! 12: * Redistribution and use in source and binary forms, with or without
! 13: * modification, are permitted provided that the following conditions
! 14: * are met:
! 15: * 1. Redistributions of source code must retain the above copyright
! 16: * notice, this list of conditions and the following disclaimer,
! 17: * without modification, immediately at the beginning of the file.
! 18: * 2. The name of the author may not be used to endorse or promote products
! 19: * derived from this software without specific prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 24: * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
! 25: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 26: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 27: * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 29: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
! 30: * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
! 31: * THE POSSIBILITY OF SUCH DAMAGE.
! 32: *
! 33: *-------------------------------------------------------------------------
! 34: */
! 35: #include <sys/param.h>
! 36: #include <sys/systm.h>
! 37: #include <sys/kernel.h>
! 38: #include <sys/buf.h>
! 39: #include <sys/device.h>
! 40:
! 41: #include <machine/bus.h>
! 42: #include <machine/intr.h>
! 43:
! 44: #include <scsi/scsi_all.h>
! 45: #include <scsi/scsiconf.h>
! 46: #include <scsi/scsi_message.h>
! 47:
! 48: #include <dev/ic/iha.h>
! 49:
! 50: /* #define IHA_DEBUG_STATE */
! 51:
! 52: struct cfdriver iha_cd = {
! 53: NULL, "iha", DV_DULL
! 54: };
! 55:
! 56: struct scsi_adapter iha_switch = {
! 57: iha_scsi_cmd, /* int (*scsi_cmd)(struct scsi_xfer *); */
! 58: iha_minphys, /* void (*scsi_minphys)(struct buf *); */
! 59: NULL, /* int (*open_target_lu)(void); */
! 60: NULL /* int (*close_target_lu)(void); */
! 61: };
! 62:
! 63: struct scsi_device iha_dev = {
! 64: NULL, /* Use default error handler */
! 65: NULL, /* have a queue, served by this */
! 66: NULL, /* have no async handler */
! 67: NULL, /* Use default 'done' routine */
! 68: };
! 69:
! 70: /*
! 71: * SCSI Rate Table, indexed by FLAG_SCSI_RATE field of
! 72: * TCS_Flags.
! 73: */
! 74: static const u_int8_t iha_rate_tbl[] = {
! 75: /* fast 20 */
! 76: /* nanosecond divide by 4 */
! 77: 12, /* 50ns, 20M */
! 78: 18, /* 75ns, 13.3M */
! 79: 25, /* 100ns, 10M */
! 80: 31, /* 125ns, 8M */
! 81: 37, /* 150ns, 6.6M */
! 82: 43, /* 175ns, 5.7M */
! 83: 50, /* 200ns, 5M */
! 84: 62 /* 250ns, 4M */
! 85: };
! 86:
! 87: int iha_setup_sg_list(struct iha_softc *, struct iha_scb *);
! 88: u_int8_t iha_data_over_run(struct iha_scb *);
! 89: int iha_push_sense_request(struct iha_softc *, struct iha_scb *);
! 90: void iha_timeout(void *);
! 91: int iha_alloc_scbs(struct iha_softc *);
! 92: void iha_read_eeprom(bus_space_tag_t, bus_space_handle_t,
! 93: struct iha_nvram *);
! 94: void iha_se2_instr(bus_space_tag_t, bus_space_handle_t, u_int8_t);
! 95: u_int16_t iha_se2_rd(bus_space_tag_t, bus_space_handle_t, u_int8_t);
! 96: void iha_reset_scsi_bus(struct iha_softc *);
! 97: void iha_reset_chip(struct iha_softc *,
! 98: bus_space_tag_t, bus_space_handle_t);
! 99: void iha_reset_dma(bus_space_tag_t, bus_space_handle_t);
! 100: void iha_reset_tcs(struct tcs *, u_int8_t);
! 101: void iha_print_info(struct iha_softc *, int);
! 102: void iha_done_scb(struct iha_softc *, struct iha_scb *);
! 103: void iha_exec_scb(struct iha_softc *, struct iha_scb *);
! 104: void iha_main(struct iha_softc *, bus_space_tag_t, bus_space_handle_t);
! 105: void iha_scsi(struct iha_softc *, bus_space_tag_t, bus_space_handle_t);
! 106: int iha_wait(struct iha_softc *, bus_space_tag_t, bus_space_handle_t,
! 107: u_int8_t);
! 108: void iha_mark_busy_scb(struct iha_scb *);
! 109: void iha_append_free_scb(struct iha_softc *, struct iha_scb *);
! 110: struct iha_scb *iha_pop_free_scb(struct iha_softc *);
! 111: void iha_append_done_scb(struct iha_softc *, struct iha_scb *,
! 112: u_int8_t);
! 113: struct iha_scb *iha_pop_done_scb(struct iha_softc *);
! 114: void iha_append_pend_scb(struct iha_softc *, struct iha_scb *);
! 115: void iha_push_pend_scb(struct iha_softc *, struct iha_scb *);
! 116: struct iha_scb *iha_find_pend_scb(struct iha_softc *);
! 117: void iha_sync_done(struct iha_softc *,
! 118: bus_space_tag_t, bus_space_handle_t);
! 119: void iha_wide_done(struct iha_softc *,
! 120: bus_space_tag_t, bus_space_handle_t);
! 121: void iha_bad_seq(struct iha_softc *);
! 122: int iha_next_state(struct iha_softc *,
! 123: bus_space_tag_t, bus_space_handle_t);
! 124: int iha_state_1(struct iha_softc *,
! 125: bus_space_tag_t, bus_space_handle_t);
! 126: int iha_state_2(struct iha_softc *,
! 127: bus_space_tag_t, bus_space_handle_t);
! 128: int iha_state_3(struct iha_softc *,
! 129: bus_space_tag_t, bus_space_handle_t);
! 130: int iha_state_4(struct iha_softc *,
! 131: bus_space_tag_t, bus_space_handle_t);
! 132: int iha_state_5(struct iha_softc *,
! 133: bus_space_tag_t, bus_space_handle_t);
! 134: int iha_state_6(struct iha_softc *,
! 135: bus_space_tag_t, bus_space_handle_t);
! 136: int iha_state_8(struct iha_softc *,
! 137: bus_space_tag_t, bus_space_handle_t);
! 138: void iha_set_ssig(bus_space_tag_t,
! 139: bus_space_handle_t, u_int8_t, u_int8_t);
! 140: int iha_xpad_in(struct iha_softc *,
! 141: bus_space_tag_t, bus_space_handle_t);
! 142: int iha_xpad_out(struct iha_softc *,
! 143: bus_space_tag_t, bus_space_handle_t);
! 144: int iha_xfer_data(struct iha_scb *,
! 145: bus_space_tag_t, bus_space_handle_t,
! 146: int direction);
! 147: int iha_status_msg(struct iha_softc *,
! 148: bus_space_tag_t, bus_space_handle_t);
! 149: int iha_msgin(struct iha_softc *, bus_space_tag_t, bus_space_handle_t);
! 150: int iha_msgin_sdtr(struct iha_softc *);
! 151: int iha_msgin_extended(struct iha_softc *,
! 152: bus_space_tag_t, bus_space_handle_t);
! 153: int iha_msgin_ignore_wid_resid(struct iha_softc *,
! 154: bus_space_tag_t, bus_space_handle_t);
! 155: int iha_msgout(struct iha_softc *,
! 156: bus_space_tag_t, bus_space_handle_t, u_int8_t);
! 157: int iha_msgout_extended(struct iha_softc *,
! 158: bus_space_tag_t, bus_space_handle_t);
! 159: void iha_msgout_abort(struct iha_softc *,
! 160: bus_space_tag_t, bus_space_handle_t, u_int8_t);
! 161: int iha_msgout_reject(struct iha_softc *,
! 162: bus_space_tag_t, bus_space_handle_t);
! 163: int iha_msgout_sdtr(struct iha_softc *,
! 164: bus_space_tag_t, bus_space_handle_t);
! 165: int iha_msgout_wdtr(struct iha_softc *,
! 166: bus_space_tag_t, bus_space_handle_t);
! 167: void iha_select(struct iha_softc *,
! 168: bus_space_tag_t, bus_space_handle_t,
! 169: struct iha_scb *, u_int8_t);
! 170: void iha_busfree(struct iha_softc *,
! 171: bus_space_tag_t, bus_space_handle_t);
! 172: int iha_resel(struct iha_softc *, bus_space_tag_t, bus_space_handle_t);
! 173: void iha_abort_xs(struct iha_softc *, struct scsi_xfer *, u_int8_t);
! 174:
! 175: /*
! 176: * iha_intr - the interrupt service routine for the iha driver
! 177: */
! 178: int
! 179: iha_intr(arg)
! 180: void *arg;
! 181: {
! 182: bus_space_handle_t ioh;
! 183: struct iha_softc *sc;
! 184: bus_space_tag_t iot;
! 185: int s;
! 186:
! 187: sc = (struct iha_softc *)arg;
! 188: iot = sc->sc_iot;
! 189: ioh = sc->sc_ioh;
! 190:
! 191: if ((bus_space_read_1(iot, ioh, TUL_STAT0) & INTPD) == 0)
! 192: return (0);
! 193:
! 194: s = splbio(); /* XXX - Or are interrupts off when ISR's are called? */
! 195:
! 196: if (sc->HCS_Semaph != SEMAPH_IN_MAIN) {
! 197: /* XXX - need these inside a splbio()/splx()? */
! 198: bus_space_write_1(iot, ioh, TUL_IMSK, MASK_ALL);
! 199: sc->HCS_Semaph = SEMAPH_IN_MAIN;
! 200:
! 201: iha_main(sc, iot, ioh);
! 202:
! 203: sc->HCS_Semaph = ~SEMAPH_IN_MAIN;
! 204: bus_space_write_1(iot, ioh, TUL_IMSK, (MASK_ALL & ~MSCMP));
! 205: }
! 206:
! 207: splx(s);
! 208:
! 209: return (1);
! 210: }
! 211:
! 212: /*
! 213: * iha_setup_sg_list - initialize scatter gather list of pScb from
! 214: * pScb->SCB_DataDma.
! 215: */
! 216: int
! 217: iha_setup_sg_list(sc, pScb)
! 218: struct iha_softc *sc;
! 219: struct iha_scb *pScb;
! 220: {
! 221: bus_dma_segment_t *segs = pScb->SCB_DataDma->dm_segs;
! 222: int i, error, nseg = pScb->SCB_DataDma->dm_nsegs;
! 223:
! 224: if (nseg > 1) {
! 225: error = bus_dmamap_load(sc->sc_dmat, pScb->SCB_SGDma,
! 226: pScb->SCB_SGList, sizeof(pScb->SCB_SGList), NULL,
! 227: (pScb->SCB_Flags & SCSI_NOSLEEP) ?
! 228: BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
! 229: if (error) {
! 230: sc_print_addr(pScb->SCB_Xs->sc_link);
! 231: printf("error %d loading SG list dma map\n", error);
! 232: return (error);
! 233: }
! 234:
! 235: /*
! 236: * Only set FLAG_SG when SCB_SGDma is loaded so iha_scsi_done
! 237: * will not unload an unloaded map.
! 238: */
! 239: pScb->SCB_Flags |= FLAG_SG;
! 240: bzero(pScb->SCB_SGList, sizeof(pScb->SCB_SGList));
! 241:
! 242: pScb->SCB_SGIdx = 0;
! 243: pScb->SCB_SGCount = nseg;
! 244:
! 245: for (i=0; i < nseg; i++) {
! 246: pScb->SCB_SGList[i].SG_Len = segs[i].ds_len;
! 247: pScb->SCB_SGList[i].SG_Addr = segs[i].ds_addr;
! 248: }
! 249:
! 250: bus_dmamap_sync(sc->sc_dmat, pScb->SCB_SGDma,
! 251: 0, sizeof(pScb->SCB_SGList), BUS_DMASYNC_PREWRITE);
! 252: }
! 253:
! 254: return (0);
! 255: }
! 256:
! 257: /*
! 258: * iha_scsi_cmd - start execution of a SCSI command. This is called
! 259: * from the generic SCSI driver via the field
! 260: * sc_adapter.scsi_cmd of iha_softc.
! 261: */
! 262: int
! 263: iha_scsi_cmd(xs)
! 264: struct scsi_xfer *xs;
! 265: {
! 266: struct iha_scb *pScb;
! 267: struct scsi_link *sc_link = xs->sc_link;
! 268: struct iha_softc *sc = sc_link->adapter_softc;
! 269: int error;
! 270:
! 271: if ((xs->cmdlen > 12) || (sc_link->target >= IHA_MAX_TARGETS)) {
! 272: xs->error = XS_DRIVER_STUFFUP;
! 273: return (COMPLETE);
! 274: }
! 275:
! 276: pScb = iha_pop_free_scb(sc);
! 277: if (pScb == NULL) {
! 278: /* XXX - different xs->error/return if
! 279: * SCSI_POLL/_NOSLEEP? */
! 280: return (TRY_AGAIN_LATER);
! 281: }
! 282:
! 283: pScb->SCB_Target = sc_link->target;
! 284: pScb->SCB_Lun = sc_link->lun;
! 285: pScb->SCB_Tcs = &sc->HCS_Tcs[pScb->SCB_Target];
! 286: pScb->SCB_Flags = xs->flags;
! 287: pScb->SCB_Ident = MSG_IDENTIFYFLAG |
! 288: (pScb->SCB_Lun & MSG_IDENTIFY_LUNMASK);
! 289:
! 290: if ((xs->cmd->opcode != REQUEST_SENSE)
! 291: && ((pScb->SCB_Flags & SCSI_POLL) == 0))
! 292: pScb->SCB_Ident |= MSG_IDENTIFY_DISCFLAG;
! 293:
! 294: pScb->SCB_Xs = xs;
! 295: pScb->SCB_CDBLen = xs->cmdlen;
! 296: bcopy(xs->cmd, &pScb->SCB_CDB, xs->cmdlen);
! 297:
! 298: pScb->SCB_BufCharsLeft = pScb->SCB_BufChars = xs->datalen;
! 299:
! 300: if ((pScb->SCB_Flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) != 0) {
! 301: #ifdef TFS
! 302: if (pScb->SCB_Flags & SCSI_DATA_UIO)
! 303: error = bus_dmamap_load_uio(sc->sc_dmat,
! 304: pScb->SCB_DataDma, (struct uio *)xs->data,
! 305: (pScb->SCB_Flags & SCSI_NOSLEEP) ?
! 306: BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
! 307: else
! 308: #endif /* TFS */
! 309: error = bus_dmamap_load(sc->sc_dmat, pScb->SCB_DataDma,
! 310: xs->data, pScb->SCB_BufChars, NULL,
! 311: (pScb->SCB_Flags & SCSI_NOSLEEP) ?
! 312: BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
! 313:
! 314: if (error) {
! 315: sc_print_addr(xs->sc_link);
! 316: if (error == EFBIG)
! 317: printf("buffer needs >%d dma segments\n",
! 318: IHA_MAX_SG_ENTRIES);
! 319: else
! 320: printf("error %d loading buffer dma map\n",
! 321: error);
! 322:
! 323: iha_append_free_scb(sc, pScb);
! 324:
! 325: xs->error = XS_DRIVER_STUFFUP;
! 326: return (COMPLETE);
! 327: }
! 328: bus_dmamap_sync(sc->sc_dmat, pScb->SCB_DataDma,
! 329: 0, pScb->SCB_BufChars,
! 330: (pScb->SCB_Flags & SCSI_DATA_IN) ?
! 331: BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
! 332:
! 333: error = iha_setup_sg_list(sc, pScb);
! 334: if (error) {
! 335: bus_dmamap_unload(sc->sc_dmat, pScb->SCB_DataDma);
! 336: xs->error = XS_DRIVER_STUFFUP;
! 337: return (COMPLETE);
! 338: }
! 339:
! 340: }
! 341:
! 342: /*
! 343: * Always initialize the stimeout structure as it may
! 344: * contain garbage that confuses timeout_del() later on.
! 345: * But, timeout_add() ONLY if we are not polling.
! 346: */
! 347: timeout_set(&xs->stimeout, iha_timeout, pScb);
! 348: if ((pScb->SCB_Flags & SCSI_POLL) == 0)
! 349: timeout_add(&xs->stimeout, (xs->timeout/1000) * hz);
! 350:
! 351: iha_exec_scb(sc, pScb);
! 352:
! 353: if ((xs->flags & ITSDONE) == 0)
! 354: return (SUCCESSFULLY_QUEUED);
! 355: else
! 356: return (COMPLETE);
! 357: }
! 358:
! 359: /*
! 360: * iha_init_tulip - initialize the inic-940/950 card and the rest of the
! 361: * iha_softc structure supplied
! 362: */
! 363: int
! 364: iha_init_tulip(sc)
! 365: struct iha_softc *sc;
! 366: {
! 367: struct iha_scb *pScb;
! 368: struct iha_nvram_scsi *pScsi;
! 369: bus_space_handle_t ioh;
! 370: struct iha_nvram iha_nvram;
! 371: bus_space_tag_t iot;
! 372: int i, error;
! 373:
! 374: iot = sc->sc_iot;
! 375: ioh = sc->sc_ioh;
! 376:
! 377: iha_read_eeprom(iot, ioh, &iha_nvram);
! 378:
! 379: pScsi = &iha_nvram.NVM_Scsi[0];
! 380:
! 381: /*
! 382: * fill in the prototype scsi_link.
! 383: */
! 384: sc->sc_link.adapter_softc = sc;
! 385: sc->sc_link.adapter = &iha_switch;
! 386: sc->sc_link.device = &iha_dev;
! 387: sc->sc_link.openings = 4; /* # xs's allowed per device */
! 388: sc->sc_link.adapter_target = pScsi->NVM_SCSI_Id;
! 389: sc->sc_link.adapter_buswidth = pScsi->NVM_SCSI_Targets;
! 390:
! 391: /*
! 392: * fill in the rest of the iha_softc fields
! 393: */
! 394: sc->HCS_Semaph = ~SEMAPH_IN_MAIN;
! 395: sc->HCS_JSStatus0 = 0;
! 396: sc->HCS_ActScb = NULL;
! 397:
! 398: TAILQ_INIT(&sc->HCS_FreeScb);
! 399: TAILQ_INIT(&sc->HCS_PendScb);
! 400: TAILQ_INIT(&sc->HCS_DoneScb);
! 401:
! 402: error = iha_alloc_scbs(sc);
! 403: if (error != 0)
! 404: return (error);
! 405:
! 406: for (i = 0, pScb = sc->HCS_Scb; i < IHA_MAX_SCB; i++, pScb++) {
! 407: pScb->SCB_TagId = i;
! 408:
! 409: error = bus_dmamap_create(sc->sc_dmat,
! 410: (IHA_MAX_SG_ENTRIES-1) * PAGE_SIZE, IHA_MAX_SG_ENTRIES,
! 411: (IHA_MAX_SG_ENTRIES-1) * PAGE_SIZE, 0,
! 412: BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &pScb->SCB_DataDma);
! 413:
! 414: if (error != 0) {
! 415: printf("%s: couldn't create SCB data DMA map, error = %d\n",
! 416: sc->sc_dev.dv_xname, error);
! 417: return (error);
! 418: }
! 419:
! 420: error = bus_dmamap_create(sc->sc_dmat,
! 421: sizeof(pScb->SCB_SGList), 1,
! 422: sizeof(pScb->SCB_SGList), 0,
! 423: BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
! 424: &pScb->SCB_SGDma);
! 425: if (error != 0) {
! 426: printf("%s: couldn't create SCB SG DMA map, error = %d\n",
! 427: sc->sc_dev.dv_xname, error);
! 428: return (error);
! 429: }
! 430:
! 431: TAILQ_INSERT_TAIL(&sc->HCS_FreeScb, pScb, SCB_ScbList);
! 432: }
! 433:
! 434: /* Mask all the interrupts */
! 435: bus_space_write_1(iot, ioh, TUL_IMSK, MASK_ALL);
! 436:
! 437: /* Stop any I/O and reset the scsi module */
! 438: iha_reset_dma(iot, ioh);
! 439: bus_space_write_1(iot, ioh, TUL_SCTRL0, RSMOD);
! 440:
! 441: /* Program HBA's SCSI ID */
! 442: bus_space_write_1(iot, ioh, TUL_SID, sc->sc_link.adapter_target << 4);
! 443:
! 444: /*
! 445: * Configure the channel as requested by the NVRAM settings read
! 446: * into iha_nvram by iha_read_eeprom() above.
! 447: */
! 448:
! 449: if ((pScsi->NVM_SCSI_Cfg & CFG_EN_PAR) != 0)
! 450: sc->HCS_SConf1 = (SCONFIG0DEFAULT | SPCHK);
! 451: else
! 452: sc->HCS_SConf1 = (SCONFIG0DEFAULT);
! 453: bus_space_write_1(iot, ioh, TUL_SCONFIG0, sc->HCS_SConf1);
! 454:
! 455: /* selection time out in units of 1.6385 millisecond = 250 ms */
! 456: bus_space_write_1(iot, ioh, TUL_STIMO, 153);
! 457:
! 458: /* Enable desired SCSI termination configuration read from eeprom */
! 459: bus_space_write_1(iot, ioh, TUL_DCTRL0,
! 460: (pScsi->NVM_SCSI_Cfg & (CFG_ACT_TERM1 | CFG_ACT_TERM2)));
! 461:
! 462: bus_space_write_1(iot, ioh, TUL_GCTRL1,
! 463: ((pScsi->NVM_SCSI_Cfg & CFG_AUTO_TERM) >> 4)
! 464: | (bus_space_read_1(iot, ioh, TUL_GCTRL1) & (~ATDEN)));
! 465:
! 466: for (i = 0; i < IHA_MAX_TARGETS; i++) {
! 467: sc->HCS_Tcs[i].TCS_Flags = pScsi->NVM_SCSI_TargetFlags[i];
! 468: iha_reset_tcs(&sc->HCS_Tcs[i], sc->HCS_SConf1);
! 469: }
! 470:
! 471: iha_reset_chip(sc, iot, ioh);
! 472: bus_space_write_1(iot, ioh, TUL_SIEN, ALL_INTERRUPTS);
! 473:
! 474: return (0);
! 475: }
! 476:
! 477: /*
! 478: * iha_minphys - reduce bp->b_bcount to something less than
! 479: * or equal to the largest I/O possible through
! 480: * the adapter. Called from higher layers
! 481: * via sc->sc_adapter.scsi_minphys.
! 482: */
! 483: void
! 484: iha_minphys(bp)
! 485: struct buf *bp;
! 486: {
! 487: if (bp->b_bcount > ((IHA_MAX_SG_ENTRIES - 1) * PAGE_SIZE))
! 488: bp->b_bcount = ((IHA_MAX_SG_ENTRIES - 1) * PAGE_SIZE);
! 489:
! 490: minphys(bp);
! 491: }
! 492:
! 493: /*
! 494: * iha_reset_dma - abort any active DMA xfer, reset tulip FIFO.
! 495: */
! 496: void
! 497: iha_reset_dma(iot, ioh)
! 498: bus_space_tag_t iot;
! 499: bus_space_handle_t ioh;
! 500: {
! 501: if ((bus_space_read_1(iot, ioh, TUL_ISTUS1) & XPEND) != 0) {
! 502: /* if DMA xfer is pending, abort DMA xfer */
! 503: bus_space_write_1(iot, ioh, TUL_DCMD, ABTXFR);
! 504: /* wait Abort DMA xfer done */
! 505: while ((bus_space_read_1(iot, ioh, TUL_ISTUS0) & DABT) == 0)
! 506: ;
! 507: }
! 508:
! 509: bus_space_write_1(iot, ioh, TUL_SCTRL0, RSFIFO);
! 510: }
! 511:
! 512: /*
! 513: * iha_pop_free_scb - return the first free SCB, or NULL if there are none.
! 514: */
! 515: struct iha_scb *
! 516: iha_pop_free_scb(sc)
! 517: struct iha_softc *sc;
! 518: {
! 519: struct iha_scb *pScb;
! 520: int s;
! 521:
! 522: s = splbio();
! 523:
! 524: pScb = TAILQ_FIRST(&sc->HCS_FreeScb);
! 525:
! 526: if (pScb != NULL) {
! 527: pScb->SCB_Status = STATUS_RENT;
! 528: TAILQ_REMOVE(&sc->HCS_FreeScb, pScb, SCB_ScbList);
! 529: }
! 530:
! 531: splx(s);
! 532:
! 533: return (pScb);
! 534: }
! 535:
! 536: /*
! 537: * iha_append_free_scb - append the supplied SCB to the tail of the
! 538: * HCS_FreeScb queue after clearing and resetting
! 539: * everything possible.
! 540: */
! 541: void
! 542: iha_append_free_scb(sc, pScb)
! 543: struct iha_softc *sc;
! 544: struct iha_scb *pScb;
! 545: {
! 546: int s;
! 547:
! 548: s = splbio();
! 549:
! 550: if (pScb == sc->HCS_ActScb)
! 551: sc->HCS_ActScb = NULL;
! 552:
! 553: pScb->SCB_Status = STATUS_QUEUED;
! 554: pScb->SCB_HaStat = HOST_OK;
! 555: pScb->SCB_TaStat = SCSI_OK;
! 556:
! 557: pScb->SCB_NxtStat = 0;
! 558: pScb->SCB_Flags = 0;
! 559: pScb->SCB_Target = 0;
! 560: pScb->SCB_Lun = 0;
! 561: pScb->SCB_CDBLen = 0;
! 562: pScb->SCB_Ident = 0;
! 563: pScb->SCB_TagMsg = 0;
! 564:
! 565: pScb->SCB_BufChars = 0;
! 566: pScb->SCB_BufCharsLeft = 0;
! 567:
! 568: pScb->SCB_Xs = NULL;
! 569: pScb->SCB_Tcs = NULL;
! 570:
! 571: bzero(pScb->SCB_CDB, sizeof(pScb->SCB_CDB));
! 572:
! 573: /*
! 574: * SCB_TagId is set at initialization and never changes
! 575: */
! 576:
! 577: TAILQ_INSERT_TAIL(&sc->HCS_FreeScb, pScb, SCB_ScbList);
! 578:
! 579: splx(s);
! 580: }
! 581:
! 582: void
! 583: iha_append_pend_scb(sc, pScb)
! 584: struct iha_softc *sc;
! 585: struct iha_scb *pScb;
! 586: {
! 587: /* ASSUMPTION: only called within a splbio()/splx() pair */
! 588:
! 589: if (pScb == sc->HCS_ActScb)
! 590: sc->HCS_ActScb = NULL;
! 591:
! 592: pScb->SCB_Status = STATUS_QUEUED;
! 593:
! 594: TAILQ_INSERT_TAIL(&sc->HCS_PendScb, pScb, SCB_ScbList);
! 595: }
! 596:
! 597: void
! 598: iha_push_pend_scb(sc, pScb)
! 599: struct iha_softc *sc;
! 600: struct iha_scb *pScb;
! 601: {
! 602: int s;
! 603:
! 604: s = splbio();
! 605:
! 606: if (pScb == sc->HCS_ActScb)
! 607: sc->HCS_ActScb = NULL;
! 608:
! 609: pScb->SCB_Status = STATUS_QUEUED;
! 610:
! 611: TAILQ_INSERT_HEAD(&sc->HCS_PendScb, pScb, SCB_ScbList);
! 612:
! 613: splx(s);
! 614: }
! 615:
! 616: /*
! 617: * iha_find_pend_scb - scan the pending queue for a SCB that can be
! 618: * processed immediately. Return NULL if none found
! 619: * and a pointer to the SCB if one is found. If there
! 620: * is an active SCB, return NULL!
! 621: */
! 622: struct iha_scb *
! 623: iha_find_pend_scb(sc)
! 624: struct iha_softc *sc;
! 625: {
! 626: struct iha_scb *pScb;
! 627: struct tcs *pTcs;
! 628: int s;
! 629:
! 630: s = splbio();
! 631:
! 632: if (sc->HCS_ActScb != NULL)
! 633: pScb = NULL;
! 634:
! 635: else
! 636: TAILQ_FOREACH(pScb, &sc->HCS_PendScb, SCB_ScbList) {
! 637: if ((pScb->SCB_Flags & SCSI_RESET) != 0)
! 638: /* ALWAYS willing to reset a device */
! 639: break;
! 640:
! 641: pTcs = pScb->SCB_Tcs;
! 642:
! 643: if ((pScb->SCB_TagMsg) != 0) {
! 644: /*
! 645: * A Tagged I/O. OK to start If no
! 646: * non-tagged I/O is active on the same
! 647: * target
! 648: */
! 649: if (pTcs->TCS_NonTagScb == NULL)
! 650: break;
! 651:
! 652: } else if (pScb->SCB_CDB[0] == REQUEST_SENSE) {
! 653: /*
! 654: * OK to do a non-tagged request sense
! 655: * even if a non-tagged I/O has been
! 656: * started, because we don't allow any
! 657: * disconnect during a request sense op
! 658: */
! 659: break;
! 660:
! 661: } else if (pTcs->TCS_TagCnt == 0) {
! 662: /*
! 663: * No tagged I/O active on this target,
! 664: * ok to start a non-tagged one if one
! 665: * is not already active
! 666: */
! 667: if (pTcs->TCS_NonTagScb == NULL)
! 668: break;
! 669: }
! 670: }
! 671:
! 672: splx(s);
! 673:
! 674: return (pScb);
! 675: }
! 676:
! 677: void
! 678: iha_mark_busy_scb(pScb)
! 679: struct iha_scb *pScb;
! 680: {
! 681: int s;
! 682:
! 683: s = splbio();
! 684:
! 685: pScb->SCB_Status = STATUS_BUSY;
! 686:
! 687: if (pScb->SCB_TagMsg == 0)
! 688: pScb->SCB_Tcs->TCS_NonTagScb = pScb;
! 689: else
! 690: pScb->SCB_Tcs->TCS_TagCnt++;
! 691:
! 692: splx(s);
! 693: }
! 694:
! 695: void
! 696: iha_append_done_scb(sc, pScb, hastat)
! 697: struct iha_softc *sc;
! 698: struct iha_scb *pScb;
! 699: u_int8_t hastat;
! 700: {
! 701: struct tcs *pTcs;
! 702: int s;
! 703:
! 704: s = splbio();
! 705:
! 706: if (pScb->SCB_Xs != NULL)
! 707: timeout_del(&pScb->SCB_Xs->stimeout);
! 708:
! 709: if (pScb == sc->HCS_ActScb)
! 710: sc->HCS_ActScb = NULL;
! 711:
! 712: pTcs = pScb->SCB_Tcs;
! 713:
! 714: if (pScb->SCB_TagMsg != 0) {
! 715: if (pTcs->TCS_TagCnt)
! 716: pTcs->TCS_TagCnt--;
! 717: } else if (pTcs->TCS_NonTagScb == pScb)
! 718: pTcs->TCS_NonTagScb = NULL;
! 719:
! 720: pScb->SCB_Status = STATUS_QUEUED;
! 721: pScb->SCB_HaStat = hastat;
! 722:
! 723: TAILQ_INSERT_TAIL(&sc->HCS_DoneScb, pScb, SCB_ScbList);
! 724:
! 725: splx(s);
! 726: }
! 727:
! 728: struct iha_scb *
! 729: iha_pop_done_scb(sc)
! 730: struct iha_softc *sc;
! 731: {
! 732: struct iha_scb *pScb;
! 733: int s;
! 734:
! 735: s = splbio();
! 736:
! 737: pScb = TAILQ_FIRST(&sc->HCS_DoneScb);
! 738:
! 739: if (pScb != NULL) {
! 740: pScb->SCB_Status = STATUS_RENT;
! 741: TAILQ_REMOVE(&sc->HCS_DoneScb, pScb, SCB_ScbList);
! 742: }
! 743:
! 744: splx(s);
! 745:
! 746: return (pScb);
! 747: }
! 748:
! 749: /*
! 750: * iha_abort_xs - find the SCB associated with the supplied xs and
! 751: * stop all processing on it, moving it to the done
! 752: * queue with the supplied host status value.
! 753: */
! 754: void
! 755: iha_abort_xs(sc, xs, hastat)
! 756: struct iha_softc *sc;
! 757: struct scsi_xfer *xs;
! 758: u_int8_t hastat;
! 759: {
! 760: struct iha_scb *pScb, *next;
! 761: int i, s;
! 762:
! 763: s = splbio();
! 764:
! 765: /* Check the pending queue for the SCB pointing to xs */
! 766:
! 767: for (pScb = TAILQ_FIRST(&sc->HCS_PendScb); pScb != NULL; pScb = next) {
! 768: next = TAILQ_NEXT(pScb, SCB_ScbList);
! 769: if (pScb->SCB_Xs == xs) {
! 770: TAILQ_REMOVE(&sc->HCS_PendScb, pScb, SCB_ScbList);
! 771: iha_append_done_scb(sc, pScb, hastat);
! 772: splx(s);
! 773: return;
! 774: }
! 775: }
! 776:
! 777: /*
! 778: * If that didn't work, check all BUSY/SELECTING SCB's for one
! 779: * pointing to xs
! 780: */
! 781:
! 782: for (i = 0, pScb = sc->HCS_Scb; i < IHA_MAX_SCB; i++, pScb++)
! 783: switch (pScb->SCB_Status) {
! 784: case STATUS_BUSY:
! 785: case STATUS_SELECT:
! 786: if (pScb->SCB_Xs == xs) {
! 787: iha_append_done_scb(sc, pScb, hastat);
! 788: splx(s);
! 789: return;
! 790: }
! 791: break;
! 792: default:
! 793: break;
! 794: }
! 795:
! 796: splx(s);
! 797: }
! 798:
! 799: /*
! 800: * iha_bad_seq - a SCSI bus phase was encountered out of the
! 801: * correct/expected sequence. Reset the SCSI bus.
! 802: */
! 803: void
! 804: iha_bad_seq(sc)
! 805: struct iha_softc *sc;
! 806: {
! 807: struct iha_scb *pScb = sc->HCS_ActScb;
! 808:
! 809: if (pScb != NULL)
! 810: iha_append_done_scb(sc, pScb, HOST_BAD_PHAS);
! 811:
! 812: iha_reset_scsi_bus(sc);
! 813: iha_reset_chip(sc, sc->sc_iot, sc->sc_ioh);
! 814: }
! 815:
! 816: /*
! 817: * iha_push_sense_request - obtain auto sense data by pushing the
! 818: * SCB needing it back onto the pending
! 819: * queue with a REQUEST_SENSE CDB.
! 820: */
! 821: int
! 822: iha_push_sense_request(sc, pScb)
! 823: struct iha_softc *sc;
! 824: struct iha_scb *pScb;
! 825: {
! 826: struct scsi_sense *sensecmd;
! 827: int error;
! 828:
! 829: /* First sync & unload any existing DataDma and SGDma maps */
! 830: if ((pScb->SCB_Flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) != 0) {
! 831: bus_dmamap_sync(sc->sc_dmat, pScb->SCB_DataDma,
! 832: 0, pScb->SCB_BufChars,
! 833: ((pScb->SCB_Flags & SCSI_DATA_IN) ?
! 834: BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE));
! 835: bus_dmamap_unload(sc->sc_dmat, pScb->SCB_DataDma);
! 836: /* Don't unload this map again until it is reloaded */
! 837: pScb->SCB_Flags &= ~(SCSI_DATA_IN | SCSI_DATA_OUT);
! 838: }
! 839: if ((pScb->SCB_Flags & FLAG_SG) != 0) {
! 840: bus_dmamap_sync(sc->sc_dmat, pScb->SCB_SGDma,
! 841: 0, sizeof(pScb->SCB_SGList),
! 842: BUS_DMASYNC_POSTWRITE);
! 843: bus_dmamap_unload(sc->sc_dmat, pScb->SCB_SGDma);
! 844: /* Don't unload this map again until it is reloaded */
! 845: pScb->SCB_Flags &= ~FLAG_SG;
! 846: }
! 847:
! 848: pScb->SCB_BufChars = sizeof(pScb->SCB_ScsiSenseData);
! 849: pScb->SCB_BufCharsLeft = sizeof(pScb->SCB_ScsiSenseData);
! 850: bzero(&pScb->SCB_ScsiSenseData, sizeof(pScb->SCB_ScsiSenseData));
! 851:
! 852: error = bus_dmamap_load(sc->sc_dmat, pScb->SCB_DataDma,
! 853: &pScb->SCB_ScsiSenseData,
! 854: sizeof(pScb->SCB_ScsiSenseData), NULL,
! 855: (pScb->SCB_Flags & SCSI_NOSLEEP) ?
! 856: BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
! 857: if (error) {
! 858: sc_print_addr(pScb->SCB_Xs->sc_link);
! 859: printf("error %d loading request sense buffer dma map\n",
! 860: error);
! 861: return (error);
! 862: }
! 863: bus_dmamap_sync(sc->sc_dmat, pScb->SCB_DataDma,
! 864: 0, pScb->SCB_BufChars, BUS_DMASYNC_PREREAD);
! 865:
! 866: /* Save _POLL and _NOSLEEP flags. */
! 867: pScb->SCB_Flags &= SCSI_POLL | SCSI_NOSLEEP;
! 868: pScb->SCB_Flags |= FLAG_RSENS | SCSI_DATA_IN;
! 869:
! 870: error = iha_setup_sg_list(sc, pScb);
! 871: if (error)
! 872: return (error);
! 873:
! 874: pScb->SCB_Ident &= ~MSG_IDENTIFY_DISCFLAG;
! 875:
! 876: pScb->SCB_TagMsg = 0;
! 877: pScb->SCB_TaStat = SCSI_OK;
! 878:
! 879: bzero(pScb->SCB_CDB, sizeof(pScb->SCB_CDB));
! 880:
! 881: sensecmd = (struct scsi_sense *)pScb->SCB_CDB;
! 882: pScb->SCB_CDBLen = sizeof(*sensecmd);
! 883: sensecmd->opcode = REQUEST_SENSE;
! 884: sensecmd->byte2 = pScb->SCB_Xs->sc_link->lun << 5;
! 885: sensecmd->length = sizeof(pScb->SCB_ScsiSenseData);
! 886:
! 887: if ((pScb->SCB_Flags & SCSI_POLL) == 0)
! 888: timeout_add(&pScb->SCB_Xs->stimeout,
! 889: (pScb->SCB_Xs->timeout/1000) * hz);
! 890:
! 891: iha_push_pend_scb(sc, pScb);
! 892:
! 893: return (0);
! 894: }
! 895:
! 896: /*
! 897: * iha_main - process the active SCB, taking one off pending and making it
! 898: * active if necessary, and any done SCB's created as
! 899: * a result until there are no interrupts pending and no pending
! 900: * SCB's that can be started.
! 901: */
! 902: void
! 903: iha_main(sc, iot, ioh)
! 904: struct iha_softc *sc;
! 905: bus_space_tag_t iot;
! 906: bus_space_handle_t ioh;
! 907: {
! 908: struct iha_scb *pScb;
! 909:
! 910: for (;;) {
! 911: iha_scsi_label:
! 912: iha_scsi(sc, iot, ioh);
! 913:
! 914: while ((pScb = iha_pop_done_scb(sc)) != NULL) {
! 915:
! 916: switch (pScb->SCB_TaStat) {
! 917: case SCSI_TERMINATED:
! 918: case SCSI_ACA_ACTIVE:
! 919: case SCSI_CHECK:
! 920: pScb->SCB_Tcs->TCS_Flags &=
! 921: ~(FLAG_SYNC_DONE | FLAG_WIDE_DONE);
! 922:
! 923: if ((pScb->SCB_Flags & FLAG_RSENS) != 0)
! 924: /* Check condition on check condition*/
! 925: pScb->SCB_HaStat = HOST_BAD_PHAS;
! 926: else if (iha_push_sense_request(sc, pScb) != 0)
! 927: /* Could not push sense request */
! 928: pScb->SCB_HaStat = HOST_BAD_PHAS;
! 929: else
! 930: /* REQUEST SENSE ready to process */
! 931: goto iha_scsi_label;
! 932: break;
! 933:
! 934: default:
! 935: if ((pScb->SCB_Flags & FLAG_RSENS) != 0)
! 936: /*
! 937: * Return the original SCSI_CHECK, not
! 938: * the status of the request sense
! 939: * command!
! 940: */
! 941: pScb->SCB_TaStat = SCSI_CHECK;
! 942: break;
! 943: }
! 944:
! 945: iha_done_scb(sc, pScb);
! 946: }
! 947:
! 948: /*
! 949: * If there are no interrupts pending, or we can't start
! 950: * a pending sc, break out of the for(;;). Otherwise
! 951: * continue the good work with another call to
! 952: * iha_scsi().
! 953: */
! 954: if (((bus_space_read_1(iot, ioh, TUL_STAT0) & INTPD) == 0)
! 955: && (iha_find_pend_scb(sc) == NULL))
! 956: break;
! 957: }
! 958: }
! 959:
! 960: /*
! 961: * iha_scsi - service any outstanding interrupts. If there are none, try to
! 962: * start another SCB currently in the pending queue.
! 963: */
! 964: void
! 965: iha_scsi(sc, iot, ioh)
! 966: struct iha_softc *sc;
! 967: bus_space_tag_t iot;
! 968: bus_space_handle_t ioh;
! 969: {
! 970: struct iha_scb *pScb;
! 971: struct tcs *pTcs;
! 972: u_int8_t stat;
! 973: int i;
! 974:
! 975: /* service pending interrupts asap */
! 976:
! 977: stat = bus_space_read_1(iot, ioh, TUL_STAT0);
! 978: if ((stat & INTPD) != 0) {
! 979: sc->HCS_JSStatus0 = stat;
! 980: sc->HCS_JSStatus1 = bus_space_read_1(iot, ioh, TUL_STAT1);
! 981: sc->HCS_JSInt = bus_space_read_1(iot, ioh, TUL_SISTAT);
! 982:
! 983: sc->HCS_Phase = sc->HCS_JSStatus0 & PH_MASK;
! 984:
! 985: if ((sc->HCS_JSInt & SRSTD) != 0) {
! 986: iha_reset_scsi_bus(sc);
! 987: return;
! 988: }
! 989:
! 990: if ((sc->HCS_JSInt & RSELED) != 0) {
! 991: iha_resel(sc, iot, ioh);
! 992: return;
! 993: }
! 994:
! 995: if ((sc->HCS_JSInt & (STIMEO | DISCD)) != 0) {
! 996: iha_busfree(sc, iot, ioh);
! 997: return;
! 998: }
! 999:
! 1000: if ((sc->HCS_JSInt & (SCMDN | SBSRV)) != 0) {
! 1001: iha_next_state(sc, iot, ioh);
! 1002: return;
! 1003: }
! 1004:
! 1005: if ((sc->HCS_JSInt & SELED) != 0)
! 1006: iha_set_ssig(iot, ioh, 0, 0);
! 1007: }
! 1008:
! 1009: /*
! 1010: * There were no interrupts pending which required action elsewhere, so
! 1011: * see if it is possible to start the selection phase on a pending SCB
! 1012: */
! 1013: if ((pScb = iha_find_pend_scb(sc)) == NULL)
! 1014: return;
! 1015:
! 1016: pTcs = pScb->SCB_Tcs;
! 1017:
! 1018: /* program HBA's SCSI ID & target SCSI ID */
! 1019: bus_space_write_1(iot, ioh, TUL_SID,
! 1020: (sc->sc_link.adapter_target << 4) | pScb->SCB_Target);
! 1021:
! 1022: if ((pScb->SCB_Flags & SCSI_RESET) == 0) {
! 1023: bus_space_write_1(iot, ioh, TUL_SYNCM, pTcs->TCS_JS_Period);
! 1024:
! 1025: if (((pTcs->TCS_Flags & FLAG_NO_NEG_WIDE) == 0)
! 1026: ||
! 1027: ((pTcs->TCS_Flags & FLAG_NO_NEG_SYNC) == 0))
! 1028: iha_select(sc, iot, ioh, pScb, SELATNSTOP);
! 1029:
! 1030: else if (pScb->SCB_TagMsg != 0)
! 1031: iha_select(sc, iot, ioh, pScb, SEL_ATN3);
! 1032:
! 1033: else
! 1034: iha_select(sc, iot, ioh, pScb, SEL_ATN);
! 1035:
! 1036: } else {
! 1037: iha_select(sc, iot, ioh, pScb, SELATNSTOP);
! 1038: pScb->SCB_NxtStat = 8;
! 1039: }
! 1040:
! 1041: if ((pScb->SCB_Flags & SCSI_POLL) != 0) {
! 1042: for (i = pScb->SCB_Xs->timeout; i > 0; i--) {
! 1043: if (iha_wait(sc, iot, ioh, NO_OP) == -1)
! 1044: break;
! 1045: if (iha_next_state(sc, iot, ioh) == -1)
! 1046: break;
! 1047: delay(1000); /* Only happens in boot, so it's ok */
! 1048: }
! 1049:
! 1050: /*
! 1051: * Since done queue processing not done until AFTER this
! 1052: * function returns, pScb is on the done queue, not
! 1053: * the free queue at this point and still has valid data
! 1054: *
! 1055: * Conversely, xs->error has not been set yet
! 1056: */
! 1057: if (i == 0)
! 1058: iha_timeout(pScb);
! 1059:
! 1060: else if ((pScb->SCB_CDB[0] == INQUIRY)
! 1061: && (pScb->SCB_Lun == 0)
! 1062: && (pScb->SCB_HaStat == HOST_OK)
! 1063: && (pScb->SCB_TaStat == SCSI_OK))
! 1064: iha_print_info(sc, pScb->SCB_Target);
! 1065: }
! 1066: }
! 1067:
! 1068: /*
! 1069: * iha_data_over_run - return HOST_OK for all SCSI opcodes where BufCharsLeft
! 1070: * is an 'Allocation Length'. All other SCSI opcodes
! 1071: * get HOST_DO_DU as they SHOULD have xferred all the
! 1072: * data requested.
! 1073: *
! 1074: * The list of opcodes using 'Allocation Length' was
! 1075: * found by scanning all the SCSI-3 T10 drafts. See
! 1076: * www.t10.org for the curious with a .pdf reader.
! 1077: */
! 1078: u_int8_t
! 1079: iha_data_over_run(pScb)
! 1080: struct iha_scb *pScb;
! 1081: {
! 1082: switch (pScb->SCB_CDB[0]) {
! 1083: case 0x03: /* Request Sense SPC-2 */
! 1084: case 0x12: /* Inquiry SPC-2 */
! 1085: case 0x1a: /* Mode Sense (6 byte version) SPC-2 */
! 1086: case 0x1c: /* Receive Diagnostic Results SPC-2 */
! 1087: case 0x23: /* Read Format Capacities MMC-2 */
! 1088: case 0x29: /* Read Generation SBC */
! 1089: case 0x34: /* Read Position SSC-2 */
! 1090: case 0x37: /* Read Defect Data SBC */
! 1091: case 0x3c: /* Read Buffer SPC-2 */
! 1092: case 0x42: /* Read Sub Channel MMC-2 */
! 1093: case 0x43: /* Read TOC/PMA/ATIP MMC */
! 1094:
! 1095: /* XXX - 2 with same opcode of 0x44? */
! 1096: case 0x44: /* Read Header/Read Density Suprt MMC/SSC*/
! 1097:
! 1098: case 0x46: /* Get Configuration MMC-2 */
! 1099: case 0x4a: /* Get Event/Status Notification MMC-2 */
! 1100: case 0x4d: /* Log Sense SPC-2 */
! 1101: case 0x51: /* Read Disc Information MMC */
! 1102: case 0x52: /* Read Track Information MMC */
! 1103: case 0x59: /* Read Master CUE MMC */
! 1104: case 0x5a: /* Mode Sense (10 byte version) SPC-2 */
! 1105: case 0x5c: /* Read Buffer Capacity MMC */
! 1106: case 0x5e: /* Persistent Reserve In SPC-2 */
! 1107: case 0x84: /* Receive Copy Results SPC-2 */
! 1108: case 0xa0: /* Report LUNs SPC-2 */
! 1109: case 0xa3: /* Various Report requests SBC-2/SCC-2*/
! 1110: case 0xa4: /* Report Key MMC-2 */
! 1111: case 0xad: /* Read DVD Structure MMC-2 */
! 1112: case 0xb4: /* Read Element Status (Attached) SMC */
! 1113: case 0xb5: /* Request Volume Element Address SMC */
! 1114: case 0xb7: /* Read Defect Data (12 byte ver.) SBC */
! 1115: case 0xb8: /* Read Element Status (Independ.) SMC */
! 1116: case 0xba: /* Report Redundancy SCC-2 */
! 1117: case 0xbd: /* Mechanism Status MMC */
! 1118: case 0xbe: /* Report Basic Redundancy SCC-2 */
! 1119:
! 1120: return (HOST_OK);
! 1121: break;
! 1122:
! 1123: default:
! 1124: return (HOST_DO_DU);
! 1125: break;
! 1126: }
! 1127: }
! 1128:
! 1129: /*
! 1130: * iha_next_state - process the current SCB as requested in its
! 1131: * SCB_NxtStat member.
! 1132: */
! 1133: int
! 1134: iha_next_state(sc, iot, ioh)
! 1135: struct iha_softc *sc;
! 1136: bus_space_tag_t iot;
! 1137: bus_space_handle_t ioh;
! 1138: {
! 1139: if (sc->HCS_ActScb == NULL)
! 1140: return (-1);
! 1141:
! 1142: switch (sc->HCS_ActScb->SCB_NxtStat) {
! 1143: case 1:
! 1144: if (iha_state_1(sc, iot, ioh) == 3)
! 1145: goto state_3;
! 1146: break;
! 1147:
! 1148: case 2:
! 1149: switch (iha_state_2(sc, iot, ioh)) {
! 1150: case 3: goto state_3;
! 1151: case 4: goto state_4;
! 1152: default: break;
! 1153: }
! 1154: break;
! 1155:
! 1156: case 3:
! 1157: state_3:
! 1158: if (iha_state_3(sc, iot, ioh) == 4)
! 1159: goto state_4;
! 1160: break;
! 1161:
! 1162: case 4:
! 1163: state_4:
! 1164: switch (iha_state_4(sc, iot, ioh)) {
! 1165: case 0: return (0);
! 1166: case 6: goto state_6;
! 1167: default: break;
! 1168: }
! 1169: break;
! 1170:
! 1171: case 5:
! 1172: switch (iha_state_5(sc, iot, ioh)) {
! 1173: case 4: goto state_4;
! 1174: case 6: goto state_6;
! 1175: default: break;
! 1176: }
! 1177: break;
! 1178:
! 1179: case 6:
! 1180: state_6:
! 1181: iha_state_6(sc, iot, ioh);
! 1182: break;
! 1183:
! 1184: case 8:
! 1185: iha_state_8(sc, iot, ioh);
! 1186: break;
! 1187:
! 1188: default:
! 1189: #ifdef IHA_DEBUG_STATE
! 1190: sc_print_addr(sc->HCS_ActScb->SCB_Xs->sc_link);
! 1191: printf("[debug] -unknown state: %i-\n",
! 1192: sc->HCS_ActScb->SCB_NxtStat);
! 1193: #endif
! 1194: iha_bad_seq(sc);
! 1195: break;
! 1196: }
! 1197:
! 1198: return (-1);
! 1199: }
! 1200:
! 1201: /*
! 1202: * iha_state_1 - selection is complete after a SELATNSTOP. If the target
! 1203: * has put the bus into MSG_OUT phase start wide/sync
! 1204: * negotiation. Otherwise clear the FIFO and go to state 3,
! 1205: * which will send the SCSI CDB to the target.
! 1206: */
! 1207: int
! 1208: iha_state_1(sc, iot, ioh)
! 1209: struct iha_softc *sc;
! 1210: bus_space_tag_t iot;
! 1211: bus_space_handle_t ioh;
! 1212: {
! 1213: struct iha_scb *pScb = sc->HCS_ActScb;
! 1214: struct tcs *pTcs;
! 1215: u_int16_t flags;
! 1216:
! 1217: iha_mark_busy_scb(pScb);
! 1218:
! 1219: pTcs = pScb->SCB_Tcs;
! 1220:
! 1221: bus_space_write_1(iot, ioh, TUL_SCONFIG0, pTcs->TCS_SConfig0);
! 1222:
! 1223: /*
! 1224: * If we are in PHASE_MSG_OUT, send
! 1225: * a) IDENT message (with tags if appropriate)
! 1226: * b) WDTR if the target is configured to negotiate wide xfers
! 1227: * ** OR **
! 1228: * c) SDTR if the target is configured to negotiate sync xfers
! 1229: * but not wide ones
! 1230: *
! 1231: * If we are NOT, then the target is not asking for anything but
! 1232: * the data/command, so go straight to state 3.
! 1233: */
! 1234: if (sc->HCS_Phase == PHASE_MSG_OUT) {
! 1235: bus_space_write_1(iot, ioh, TUL_SCTRL1, (ESBUSIN | EHRSL));
! 1236: bus_space_write_1(iot, ioh, TUL_SFIFO, pScb->SCB_Ident);
! 1237:
! 1238: if (pScb->SCB_TagMsg != 0) {
! 1239: bus_space_write_1(iot, ioh, TUL_SFIFO,
! 1240: pScb->SCB_TagMsg);
! 1241: bus_space_write_1(iot, ioh, TUL_SFIFO,
! 1242: pScb->SCB_TagId);
! 1243: }
! 1244:
! 1245: flags = pTcs->TCS_Flags;
! 1246: if ((flags & FLAG_NO_NEG_WIDE) == 0) {
! 1247: if (iha_msgout_wdtr(sc, iot, ioh) == -1)
! 1248: return (-1);
! 1249: } else if ((flags & FLAG_NO_NEG_SYNC) == 0) {
! 1250: if (iha_msgout_sdtr(sc, iot, ioh) == -1)
! 1251: return (-1);
! 1252: }
! 1253:
! 1254: } else {
! 1255: bus_space_write_1(iot, ioh, TUL_SCTRL0, RSFIFO);
! 1256: iha_set_ssig(iot, ioh, REQ | BSY | SEL | ATN, 0);
! 1257: }
! 1258:
! 1259: return (3);
! 1260: }
! 1261:
! 1262: /*
! 1263: * iha_state_2 - selection is complete after a SEL_ATN or SEL_ATN3. If the SCSI
! 1264: * CDB has already been send, go to state 4 to start the data
! 1265: * xfer. Otherwise reset the FIFO and go to state 3, sending
! 1266: * the SCSI CDB.
! 1267: */
! 1268: int
! 1269: iha_state_2(sc, iot, ioh)
! 1270: struct iha_softc *sc;
! 1271: bus_space_tag_t iot;
! 1272: bus_space_handle_t ioh;
! 1273: {
! 1274: struct iha_scb *pScb = sc->HCS_ActScb;
! 1275:
! 1276: iha_mark_busy_scb(pScb);
! 1277:
! 1278: bus_space_write_1(iot, ioh, TUL_SCONFIG0, pScb->SCB_Tcs->TCS_SConfig0);
! 1279:
! 1280: if ((sc->HCS_JSStatus1 & CPDNE) != 0)
! 1281: return (4);
! 1282:
! 1283: bus_space_write_1(iot, ioh, TUL_SCTRL0, RSFIFO);
! 1284:
! 1285: iha_set_ssig(iot, ioh, REQ | BSY | SEL | ATN, 0);
! 1286:
! 1287: return (3);
! 1288: }
! 1289:
! 1290: /*
! 1291: * iha_state_3 - send the SCSI CDB to the target, processing any status
! 1292: * or other messages received until that is done or
! 1293: * abandoned.
! 1294: */
! 1295: int
! 1296: iha_state_3(sc, iot, ioh)
! 1297: struct iha_softc *sc;
! 1298: bus_space_tag_t iot;
! 1299: bus_space_handle_t ioh;
! 1300: {
! 1301: struct iha_scb *pScb = sc->HCS_ActScb;
! 1302: u_int16_t flags;
! 1303:
! 1304: for (;;)
! 1305: switch (sc->HCS_Phase) {
! 1306: case PHASE_CMD_OUT:
! 1307: bus_space_write_multi_1(iot, ioh, TUL_SFIFO,
! 1308: pScb->SCB_CDB, pScb->SCB_CDBLen);
! 1309: if (iha_wait(sc, iot, ioh, XF_FIFO_OUT) == -1)
! 1310: return (-1);
! 1311: else if (sc->HCS_Phase == PHASE_CMD_OUT) {
! 1312: iha_bad_seq(sc);
! 1313: return (-1);
! 1314: } else
! 1315: return (4);
! 1316:
! 1317: case PHASE_MSG_IN:
! 1318: pScb->SCB_NxtStat = 3;
! 1319: if (iha_msgin(sc, iot, ioh) == -1)
! 1320: return (-1);
! 1321: break;
! 1322:
! 1323: case PHASE_STATUS_IN:
! 1324: if (iha_status_msg(sc, iot, ioh) == -1)
! 1325: return (-1);
! 1326: break;
! 1327:
! 1328: case PHASE_MSG_OUT:
! 1329: flags = pScb->SCB_Tcs->TCS_Flags;
! 1330: if ((flags & FLAG_NO_NEG_SYNC) != 0) {
! 1331: if (iha_msgout(sc, iot, ioh, MSG_NOOP) == -1)
! 1332: return (-1);
! 1333: } else if (iha_msgout_sdtr(sc, iot, ioh) == -1)
! 1334: return (-1);
! 1335: break;
! 1336:
! 1337: default:
! 1338: #ifdef IHA_DEBUG_STATE
! 1339: sc_print_addr(pScb->SCB_Xs->sc_link);
! 1340: printf("[debug] -s3- bad phase = %d\n", sc->HCS_Phase);
! 1341: #endif
! 1342: iha_bad_seq(sc);
! 1343: return (-1);
! 1344: }
! 1345: }
! 1346:
! 1347: /*
! 1348: * iha_state_4 - start a data xfer. Handle any bus state
! 1349: * transitions until PHASE_DATA_IN/_OUT
! 1350: * or the attempt is abandoned. If there is
! 1351: * no data to xfer, go to state 6 and finish
! 1352: * processing the current SCB.
! 1353: */
! 1354: int
! 1355: iha_state_4(sc, iot, ioh)
! 1356: struct iha_softc *sc;
! 1357: bus_space_tag_t iot;
! 1358: bus_space_handle_t ioh;
! 1359: {
! 1360: struct iha_scb *pScb = sc->HCS_ActScb;
! 1361:
! 1362: if ((pScb->SCB_Flags & FLAG_DIR) == FLAG_DIR)
! 1363: return (6); /* Both dir flags set => NO xfer was requested */
! 1364:
! 1365: for (;;) {
! 1366: if (pScb->SCB_BufCharsLeft == 0)
! 1367: return (6);
! 1368:
! 1369: switch (sc->HCS_Phase) {
! 1370: case PHASE_STATUS_IN:
! 1371: if ((pScb->SCB_Flags & FLAG_DIR) != 0)
! 1372: pScb->SCB_HaStat = iha_data_over_run(pScb);
! 1373: if ((iha_status_msg(sc, iot, ioh)) == -1)
! 1374: return (-1);
! 1375: break;
! 1376:
! 1377: case PHASE_MSG_IN:
! 1378: pScb->SCB_NxtStat = 4;
! 1379: if (iha_msgin(sc, iot, ioh) == -1)
! 1380: return (-1);
! 1381: break;
! 1382:
! 1383: case PHASE_MSG_OUT:
! 1384: if ((sc->HCS_JSStatus0 & SPERR) != 0) {
! 1385: pScb->SCB_BufCharsLeft = 0;
! 1386: pScb->SCB_HaStat = HOST_SPERR;
! 1387: if (iha_msgout(sc, iot, ioh,
! 1388: MSG_INITIATOR_DET_ERR) == -1)
! 1389: return (-1);
! 1390: else
! 1391: return (6);
! 1392: } else {
! 1393: if (iha_msgout(sc, iot, ioh, MSG_NOOP) == -1)
! 1394: return (-1);
! 1395: }
! 1396: break;
! 1397:
! 1398: case PHASE_DATA_IN:
! 1399: return (iha_xfer_data(pScb, iot, ioh, SCSI_DATA_IN));
! 1400:
! 1401: case PHASE_DATA_OUT:
! 1402: return (iha_xfer_data(pScb, iot, ioh, SCSI_DATA_OUT));
! 1403:
! 1404: default:
! 1405: iha_bad_seq(sc);
! 1406: return (-1);
! 1407: }
! 1408: }
! 1409: }
! 1410:
! 1411: /*
! 1412: * iha_state_5 - handle the partial or final completion of the current
! 1413: * data xfer. If DMA is still active stop it. If there is
! 1414: * more data to xfer, go to state 4 and start the xfer.
! 1415: * If not go to state 6 and finish the SCB.
! 1416: */
! 1417: int
! 1418: iha_state_5(sc, iot, ioh)
! 1419: struct iha_softc *sc;
! 1420: bus_space_tag_t iot;
! 1421: bus_space_handle_t ioh;
! 1422: {
! 1423: struct iha_scb *pScb = sc->HCS_ActScb;
! 1424: struct iha_sg_element *pSg;
! 1425: u_int32_t cnt;
! 1426: u_int16_t period;
! 1427: u_int8_t stat;
! 1428: long xcnt; /* cannot use unsigned!! see code: if (xcnt < 0) */
! 1429:
! 1430: cnt = bus_space_read_4(iot, ioh, TUL_STCNT0) & TCNT;
! 1431:
! 1432: /*
! 1433: * Stop any pending DMA activity and check for parity error.
! 1434: */
! 1435:
! 1436: if ((bus_space_read_1(iot, ioh, TUL_DCMD) & XDIR) != 0) {
! 1437: /* Input Operation */
! 1438: if ((sc->HCS_JSStatus0 & SPERR) != 0)
! 1439: pScb->SCB_HaStat = HOST_SPERR;
! 1440:
! 1441: if ((bus_space_read_1(iot, ioh, TUL_ISTUS1) & XPEND) != 0) {
! 1442: bus_space_write_1(iot, ioh, TUL_DCTRL0,
! 1443: bus_space_read_1(iot, ioh, TUL_DCTRL0) | SXSTP);
! 1444: while (bus_space_read_1(iot, ioh, TUL_ISTUS1) & XPEND)
! 1445: ;
! 1446: }
! 1447:
! 1448: } else {
! 1449: /* Output Operation */
! 1450: if ((sc->HCS_JSStatus1 & SXCMP) == 0) {
! 1451: period = pScb->SCB_Tcs->TCS_JS_Period;
! 1452: if ((period & PERIOD_WIDE_SCSI) != 0)
! 1453: cnt += (bus_space_read_1(iot, ioh,
! 1454: TUL_SFIFOCNT) & FIFOC) << 1;
! 1455: else
! 1456: cnt += (bus_space_read_1(iot, ioh,
! 1457: TUL_SFIFOCNT) & FIFOC);
! 1458: }
! 1459:
! 1460: if ((bus_space_read_1(iot, ioh, TUL_ISTUS1) & XPEND) != 0) {
! 1461: bus_space_write_1(iot, ioh, TUL_DCMD, ABTXFR);
! 1462: do
! 1463: stat = bus_space_read_1(iot, ioh, TUL_ISTUS0);
! 1464: while ((stat & DABT) == 0);
! 1465: }
! 1466:
! 1467: if ((cnt == 1) && (sc->HCS_Phase == PHASE_DATA_OUT)) {
! 1468: if (iha_wait(sc, iot, ioh, XF_FIFO_OUT) == -1)
! 1469: return (-1);
! 1470: cnt = 0;
! 1471:
! 1472: } else if ((sc->HCS_JSStatus1 & SXCMP) == 0)
! 1473: bus_space_write_1(iot, ioh, TUL_SCTRL0, RSFIFO);
! 1474: }
! 1475:
! 1476: if (cnt == 0) {
! 1477: pScb->SCB_BufCharsLeft = 0;
! 1478: return (6);
! 1479: }
! 1480:
! 1481: /* Update active data pointer and restart the I/O at the new point */
! 1482:
! 1483: xcnt = pScb->SCB_BufCharsLeft - cnt; /* xcnt == bytes xferred */
! 1484: pScb->SCB_BufCharsLeft = cnt; /* cnt == bytes left */
! 1485:
! 1486: bus_dmamap_sync(sc->sc_dmat, pScb->SCB_SGDma,
! 1487: 0, sizeof(pScb->SCB_SGList), BUS_DMASYNC_POSTWRITE);
! 1488:
! 1489: if ((pScb->SCB_Flags & FLAG_SG) != 0) {
! 1490: pSg = &pScb->SCB_SGList[pScb->SCB_SGIdx];
! 1491: for (; pScb->SCB_SGIdx < pScb->SCB_SGCount; pSg++, pScb->SCB_SGIdx++) {
! 1492: xcnt -= pSg->SG_Len;
! 1493: if (xcnt < 0) {
! 1494: xcnt += pSg->SG_Len;
! 1495:
! 1496: pSg->SG_Addr += xcnt;
! 1497: pSg->SG_Len -= xcnt;
! 1498:
! 1499: bus_dmamap_sync(sc->sc_dmat, pScb->SCB_SGDma,
! 1500: 0, sizeof(pScb->SCB_SGList),
! 1501: BUS_DMASYNC_PREWRITE);
! 1502:
! 1503: return (4);
! 1504: }
! 1505: }
! 1506: return (6);
! 1507:
! 1508: }
! 1509:
! 1510: return (4);
! 1511: }
! 1512:
! 1513: /*
! 1514: * iha_state_6 - finish off the active scb (may require several
! 1515: * iterations if PHASE_MSG_IN) and return -1 to indicate
! 1516: * the bus is free.
! 1517: */
! 1518: int
! 1519: iha_state_6(sc, iot, ioh)
! 1520: struct iha_softc *sc;
! 1521: bus_space_tag_t iot;
! 1522: bus_space_handle_t ioh;
! 1523: {
! 1524: for (;;)
! 1525: switch (sc->HCS_Phase) {
! 1526: case PHASE_STATUS_IN:
! 1527: if (iha_status_msg(sc, iot, ioh) == -1)
! 1528: return (-1);
! 1529: break;
! 1530:
! 1531: case PHASE_MSG_IN:
! 1532: sc->HCS_ActScb->SCB_NxtStat = 6;
! 1533: if ((iha_msgin(sc, iot, ioh)) == -1)
! 1534: return (-1);
! 1535: break;
! 1536:
! 1537: case PHASE_MSG_OUT:
! 1538: if ((iha_msgout(sc, iot, ioh, MSG_NOOP)) == -1)
! 1539: return (-1);
! 1540: break;
! 1541:
! 1542: case PHASE_DATA_IN:
! 1543: if (iha_xpad_in(sc, iot, ioh) == -1)
! 1544: return (-1);
! 1545: break;
! 1546:
! 1547: case PHASE_DATA_OUT:
! 1548: if (iha_xpad_out(sc, iot, ioh) == -1)
! 1549: return (-1);
! 1550: break;
! 1551:
! 1552: default:
! 1553: iha_bad_seq(sc);
! 1554: return (-1);
! 1555: }
! 1556: }
! 1557:
! 1558: /*
! 1559: * iha_state_8 - reset the active device and all busy SCBs using it
! 1560: */
! 1561: int
! 1562: iha_state_8(sc, iot, ioh)
! 1563: struct iha_softc *sc;
! 1564: bus_space_tag_t iot;
! 1565: bus_space_handle_t ioh;
! 1566: {
! 1567: struct iha_scb *pScb;
! 1568: u_int32_t i;
! 1569: u_int8_t tar;
! 1570:
! 1571: if (sc->HCS_Phase == PHASE_MSG_OUT) {
! 1572: bus_space_write_1(iot, ioh, TUL_SFIFO, MSG_BUS_DEV_RESET);
! 1573:
! 1574: pScb = sc->HCS_ActScb;
! 1575:
! 1576: /* This SCB finished correctly -- resetting the device */
! 1577: iha_append_done_scb(sc, pScb, HOST_OK);
! 1578:
! 1579: iha_reset_tcs(pScb->SCB_Tcs, sc->HCS_SConf1);
! 1580:
! 1581: tar = pScb->SCB_Target;
! 1582: for (i = 0, pScb = sc->HCS_Scb; i < IHA_MAX_SCB; i++, pScb++)
! 1583: if (pScb->SCB_Target == tar)
! 1584: switch (pScb->SCB_Status) {
! 1585: case STATUS_BUSY:
! 1586: iha_append_done_scb(sc,
! 1587: pScb, HOST_DEV_RST);
! 1588: break;
! 1589:
! 1590: case STATUS_SELECT:
! 1591: iha_push_pend_scb(sc, pScb);
! 1592: break;
! 1593:
! 1594: default:
! 1595: break;
! 1596: }
! 1597:
! 1598: sc->HCS_Flags |= FLAG_EXPECT_DISC;
! 1599:
! 1600: if (iha_wait(sc, iot, ioh, XF_FIFO_OUT) == -1)
! 1601: return (-1);
! 1602: }
! 1603:
! 1604: iha_bad_seq(sc);
! 1605: return (-1);
! 1606: }
! 1607:
! 1608: /*
! 1609: * iha_xfer_data - initiate the DMA xfer of the data
! 1610: */
! 1611: int
! 1612: iha_xfer_data(pScb, iot, ioh, direction)
! 1613: struct iha_scb *pScb;
! 1614: bus_space_tag_t iot;
! 1615: bus_space_handle_t ioh;
! 1616: int direction;
! 1617: {
! 1618: u_int32_t xferaddr, xferlen;
! 1619: u_int8_t xfertype;
! 1620:
! 1621: if ((pScb->SCB_Flags & FLAG_DIR) != direction)
! 1622: return (6); /* wrong direction, abandon I/O */
! 1623:
! 1624: bus_space_write_4(iot, ioh, TUL_STCNT0, pScb->SCB_BufCharsLeft);
! 1625:
! 1626: if ((pScb->SCB_Flags & FLAG_SG) == 0) {
! 1627: xferaddr = pScb->SCB_DataDma->dm_segs[0].ds_addr
! 1628: + (pScb->SCB_BufChars - pScb->SCB_BufCharsLeft);
! 1629: xferlen = pScb->SCB_BufCharsLeft;
! 1630: xfertype = (direction == SCSI_DATA_IN) ? ST_X_IN : ST_X_OUT;
! 1631:
! 1632: } else {
! 1633: xferaddr = pScb->SCB_SGDma->dm_segs[0].ds_addr
! 1634: + (pScb->SCB_SGIdx * sizeof(struct iha_sg_element));
! 1635: xferlen = (pScb->SCB_SGCount - pScb->SCB_SGIdx)
! 1636: * sizeof(struct iha_sg_element);
! 1637: xfertype = (direction == SCSI_DATA_IN) ? ST_SG_IN : ST_SG_OUT;
! 1638: }
! 1639:
! 1640: bus_space_write_4(iot, ioh, TUL_DXC, xferlen);
! 1641: bus_space_write_4(iot, ioh, TUL_DXPA, xferaddr);
! 1642: bus_space_write_1(iot, ioh, TUL_DCMD, xfertype);
! 1643:
! 1644: bus_space_write_1(iot, ioh, TUL_SCMD,
! 1645: (direction == SCSI_DATA_IN) ? XF_DMA_IN : XF_DMA_OUT);
! 1646:
! 1647: pScb->SCB_NxtStat = 5;
! 1648:
! 1649: return (0);
! 1650: }
! 1651:
! 1652: int
! 1653: iha_xpad_in(sc, iot, ioh)
! 1654: struct iha_softc *sc;
! 1655: bus_space_tag_t iot;
! 1656: bus_space_handle_t ioh;
! 1657: {
! 1658: struct iha_scb *pScb = sc->HCS_ActScb;
! 1659:
! 1660: if ((pScb->SCB_Flags & FLAG_DIR) != 0)
! 1661: pScb->SCB_HaStat = HOST_DO_DU;
! 1662:
! 1663: for (;;) {
! 1664: if ((pScb->SCB_Tcs->TCS_JS_Period & PERIOD_WIDE_SCSI) != 0)
! 1665: bus_space_write_4(iot, ioh, TUL_STCNT0, 2);
! 1666: else
! 1667: bus_space_write_4(iot, ioh, TUL_STCNT0, 1);
! 1668:
! 1669: switch (iha_wait(sc, iot, ioh, XF_FIFO_IN)) {
! 1670: case -1:
! 1671: return (-1);
! 1672:
! 1673: case PHASE_DATA_IN:
! 1674: bus_space_read_1(iot, ioh, TUL_SFIFO);
! 1675: break;
! 1676:
! 1677: default:
! 1678: bus_space_write_1(iot, ioh, TUL_SCTRL0, RSFIFO);
! 1679: return (6);
! 1680: }
! 1681: }
! 1682: }
! 1683:
! 1684: int
! 1685: iha_xpad_out(sc, iot, ioh)
! 1686: struct iha_softc *sc;
! 1687: bus_space_tag_t iot;
! 1688: bus_space_handle_t ioh;
! 1689: {
! 1690: struct iha_scb *pScb = sc->HCS_ActScb;
! 1691:
! 1692: if ((pScb->SCB_Flags & FLAG_DIR) != 0)
! 1693: pScb->SCB_HaStat = HOST_DO_DU;
! 1694:
! 1695: for (;;) {
! 1696: if ((pScb->SCB_Tcs->TCS_JS_Period & PERIOD_WIDE_SCSI) != 0)
! 1697: bus_space_write_4(iot, ioh, TUL_STCNT0, 2);
! 1698: else
! 1699: bus_space_write_4(iot, ioh, TUL_STCNT0, 1);
! 1700:
! 1701: bus_space_write_1(iot, ioh, TUL_SFIFO, 0);
! 1702:
! 1703: switch (iha_wait(sc, iot, ioh, XF_FIFO_OUT)) {
! 1704: case -1:
! 1705: return (-1);
! 1706:
! 1707: case PHASE_DATA_OUT:
! 1708: break;
! 1709:
! 1710: default:
! 1711: /* Disable wide CPU to allow read 16 bits */
! 1712: bus_space_write_1(iot, ioh, TUL_SCTRL1, EHRSL);
! 1713: bus_space_write_1(iot, ioh, TUL_SCTRL0, RSFIFO);
! 1714: return (6);
! 1715: }
! 1716: }
! 1717: }
! 1718:
! 1719: int
! 1720: iha_status_msg(sc, iot, ioh)
! 1721: struct iha_softc *sc;
! 1722: bus_space_tag_t iot;
! 1723: bus_space_handle_t ioh;
! 1724: {
! 1725: struct iha_scb *pScb;
! 1726: u_int8_t msg;
! 1727: int phase;
! 1728:
! 1729: if ((phase = iha_wait(sc, iot, ioh, CMD_COMP)) == -1)
! 1730: return (-1);
! 1731:
! 1732: pScb = sc->HCS_ActScb;
! 1733:
! 1734: pScb->SCB_TaStat = bus_space_read_1(iot, ioh, TUL_SFIFO);
! 1735:
! 1736: if (phase == PHASE_MSG_OUT) {
! 1737: if ((sc->HCS_JSStatus0 & SPERR) == 0)
! 1738: bus_space_write_1(iot, ioh, TUL_SFIFO,
! 1739: MSG_NOOP);
! 1740: else
! 1741: bus_space_write_1(iot, ioh, TUL_SFIFO,
! 1742: MSG_PARITY_ERROR);
! 1743:
! 1744: return (iha_wait(sc, iot, ioh, XF_FIFO_OUT));
! 1745:
! 1746: } else if (phase == PHASE_MSG_IN) {
! 1747: msg = bus_space_read_1(iot, ioh, TUL_SFIFO);
! 1748:
! 1749: if ((sc->HCS_JSStatus0 & SPERR) != 0)
! 1750: switch (iha_wait(sc, iot, ioh, MSG_ACCEPT)) {
! 1751: case -1:
! 1752: return (-1);
! 1753: case PHASE_MSG_OUT:
! 1754: bus_space_write_1(iot, ioh, TUL_SFIFO,
! 1755: MSG_PARITY_ERROR);
! 1756: return (iha_wait(sc, iot, ioh, XF_FIFO_OUT));
! 1757: default:
! 1758: iha_bad_seq(sc);
! 1759: return (-1);
! 1760: }
! 1761:
! 1762: if (msg == MSG_CMDCOMPLETE) {
! 1763: if ((pScb->SCB_TaStat
! 1764: & (SCSI_INTERM | SCSI_BUSY)) == SCSI_INTERM) {
! 1765: iha_bad_seq(sc);
! 1766: return (-1);
! 1767: }
! 1768: sc->HCS_Flags |= FLAG_EXPECT_DONE_DISC;
! 1769: bus_space_write_1(iot, ioh, TUL_SCTRL0, RSFIFO);
! 1770: return (iha_wait(sc, iot, ioh, MSG_ACCEPT));
! 1771: }
! 1772:
! 1773: if ((msg == MSG_LINK_CMD_COMPLETE)
! 1774: || (msg == MSG_LINK_CMD_COMPLETEF)) {
! 1775: if ((pScb->SCB_TaStat
! 1776: & (SCSI_INTERM | SCSI_BUSY)) == SCSI_INTERM)
! 1777: return (iha_wait(sc, iot, ioh, MSG_ACCEPT));
! 1778: }
! 1779: }
! 1780:
! 1781: iha_bad_seq(sc);
! 1782: return (-1);
! 1783: }
! 1784:
! 1785: /*
! 1786: * iha_busfree - SCSI bus free detected as a result of a TIMEOUT or
! 1787: * DISCONNECT interrupt. Reset the tulip FIFO and
! 1788: * SCONFIG0 and enable hardware reselect. Move any active
! 1789: * SCB to HCS_DoneScb list. Return an appropriate host status
! 1790: * if an I/O was active.
! 1791: */
! 1792: void
! 1793: iha_busfree(sc, iot, ioh)
! 1794: struct iha_softc *sc;
! 1795: bus_space_tag_t iot;
! 1796: bus_space_handle_t ioh;
! 1797: {
! 1798: struct iha_scb *pScb;
! 1799:
! 1800: bus_space_write_1(iot, ioh, TUL_SCTRL0, RSFIFO);
! 1801: bus_space_write_1(iot, ioh, TUL_SCONFIG0, SCONFIG0DEFAULT);
! 1802: bus_space_write_1(iot, ioh, TUL_SCTRL1, EHRSL);
! 1803:
! 1804: pScb = sc->HCS_ActScb;
! 1805:
! 1806: if (pScb != NULL) {
! 1807: if (pScb->SCB_Status == STATUS_SELECT)
! 1808: /* selection timeout */
! 1809: iha_append_done_scb(sc, pScb, HOST_SEL_TOUT);
! 1810: else
! 1811: /* Unexpected bus free */
! 1812: iha_append_done_scb(sc, pScb, HOST_BAD_PHAS);
! 1813:
! 1814: }
! 1815: }
! 1816:
! 1817: void
! 1818: iha_reset_scsi_bus(sc)
! 1819: struct iha_softc *sc;
! 1820: {
! 1821: struct iha_scb *pScb;
! 1822: struct tcs *pTcs;
! 1823: int i, s;
! 1824:
! 1825: s = splbio();
! 1826:
! 1827: iha_reset_dma(sc->sc_iot, sc->sc_ioh);
! 1828:
! 1829: for (i = 0, pScb = sc->HCS_Scb; i < IHA_MAX_SCB; i++, pScb++)
! 1830: switch (pScb->SCB_Status) {
! 1831: case STATUS_BUSY:
! 1832: iha_append_done_scb(sc, pScb, HOST_SCSI_RST);
! 1833: break;
! 1834:
! 1835: case STATUS_SELECT:
! 1836: iha_push_pend_scb(sc, pScb);
! 1837: break;
! 1838:
! 1839: default:
! 1840: break;
! 1841: }
! 1842:
! 1843: for (i = 0, pTcs = sc->HCS_Tcs; i < IHA_MAX_TARGETS; i++, pTcs++)
! 1844: iha_reset_tcs(pTcs, sc->HCS_SConf1);
! 1845:
! 1846: splx(s);
! 1847: }
! 1848:
! 1849: /*
! 1850: * iha_resel - handle a detected SCSI bus reselection request.
! 1851: */
! 1852: int
! 1853: iha_resel(sc, iot, ioh)
! 1854: struct iha_softc *sc;
! 1855: bus_space_tag_t iot;
! 1856: bus_space_handle_t ioh;
! 1857: {
! 1858: struct iha_scb *pScb;
! 1859: struct tcs *pTcs;
! 1860: u_int8_t tag, target, lun, msg, abortmsg;
! 1861:
! 1862: if (sc->HCS_ActScb != NULL) {
! 1863: if ((sc->HCS_ActScb->SCB_Status == STATUS_SELECT))
! 1864: iha_push_pend_scb(sc, sc->HCS_ActScb);
! 1865: sc->HCS_ActScb = NULL;
! 1866: }
! 1867:
! 1868: target = bus_space_read_1(iot, ioh, TUL_SBID);
! 1869: lun = bus_space_read_1(iot, ioh, TUL_SALVC) & MSG_IDENTIFY_LUNMASK;
! 1870:
! 1871: pTcs = &sc->HCS_Tcs[target];
! 1872:
! 1873: bus_space_write_1(iot, ioh, TUL_SCONFIG0, pTcs->TCS_SConfig0);
! 1874: bus_space_write_1(iot, ioh, TUL_SYNCM, pTcs->TCS_JS_Period);
! 1875:
! 1876: abortmsg = MSG_ABORT; /* until a valid tag has been obtained */
! 1877:
! 1878: if (pTcs->TCS_NonTagScb != NULL)
! 1879: /* There is a non-tagged I/O active on the target */
! 1880: pScb = pTcs->TCS_NonTagScb;
! 1881:
! 1882: else {
! 1883: /*
! 1884: * Since there is no active non-tagged operation
! 1885: * read the tag type, the tag itself, and find
! 1886: * the appropriate pScb by indexing HCS_Scb with
! 1887: * the tag.
! 1888: */
! 1889:
! 1890: switch (iha_wait(sc, iot, ioh, MSG_ACCEPT)) {
! 1891: case -1:
! 1892: return (-1);
! 1893: case PHASE_MSG_IN:
! 1894: bus_space_write_4(iot, ioh, TUL_STCNT0, 1);
! 1895: if ((iha_wait(sc, iot, ioh, XF_FIFO_IN)) == -1)
! 1896: return (-1);
! 1897: break;
! 1898: default:
! 1899: goto abort;
! 1900: }
! 1901:
! 1902: msg = bus_space_read_1(iot, ioh, TUL_SFIFO); /* Read Tag Msg */
! 1903:
! 1904: if ((msg < MSG_SIMPLE_Q_TAG) || (msg > MSG_ORDERED_Q_TAG))
! 1905: goto abort;
! 1906:
! 1907: switch (iha_wait(sc, iot, ioh, MSG_ACCEPT)) {
! 1908: case -1:
! 1909: return (-1);
! 1910: case PHASE_MSG_IN:
! 1911: bus_space_write_4(iot, ioh, TUL_STCNT0, 1);
! 1912: if ((iha_wait(sc, iot, ioh, XF_FIFO_IN)) == -1)
! 1913: return (-1);
! 1914: break;
! 1915: default:
! 1916: goto abort;
! 1917: }
! 1918:
! 1919: tag = bus_space_read_1(iot, ioh, TUL_SFIFO); /* Read Tag ID */
! 1920: pScb = &sc->HCS_Scb[tag];
! 1921:
! 1922: abortmsg = MSG_ABORT_TAG; /* Now that we have valdid tag! */
! 1923: }
! 1924:
! 1925: if ((pScb->SCB_Target != target)
! 1926: || (pScb->SCB_Lun != lun)
! 1927: || (pScb->SCB_Status != STATUS_BUSY)) {
! 1928: abort:
! 1929: iha_msgout_abort(sc, iot, ioh, abortmsg);
! 1930: return (-1);
! 1931: }
! 1932:
! 1933: sc->HCS_ActScb = pScb;
! 1934:
! 1935: if (iha_wait(sc, iot, ioh, MSG_ACCEPT) == -1)
! 1936: return (-1);
! 1937:
! 1938: return(iha_next_state(sc, iot, ioh));
! 1939: }
! 1940:
! 1941: int
! 1942: iha_msgin(sc, iot, ioh)
! 1943: struct iha_softc *sc;
! 1944: bus_space_tag_t iot;
! 1945: bus_space_handle_t ioh;
! 1946: {
! 1947: u_int16_t flags;
! 1948: u_int8_t msg;
! 1949: int phase;
! 1950:
! 1951: for (;;) {
! 1952: if ((bus_space_read_1(iot, ioh, TUL_SFIFOCNT) & FIFOC) > 0)
! 1953: bus_space_write_1(iot, ioh, TUL_SCTRL0, RSFIFO);
! 1954:
! 1955: bus_space_write_4(iot, ioh, TUL_STCNT0, 1);
! 1956:
! 1957: phase = iha_wait(sc, iot, ioh, XF_FIFO_IN);
! 1958: msg = bus_space_read_1(iot, ioh, TUL_SFIFO);
! 1959:
! 1960: switch (msg) {
! 1961: case MSG_DISCONNECT:
! 1962: sc->HCS_Flags |= FLAG_EXPECT_DISC;
! 1963: if (iha_wait(sc, iot, ioh, MSG_ACCEPT) != -1)
! 1964: iha_bad_seq(sc);
! 1965: phase = -1;
! 1966: break;
! 1967: case MSG_SAVEDATAPOINTER:
! 1968: case MSG_RESTOREPOINTERS:
! 1969: case MSG_NOOP:
! 1970: phase = iha_wait(sc, iot, ioh, MSG_ACCEPT);
! 1971: break;
! 1972: case MSG_MESSAGE_REJECT:
! 1973: /* XXX - need to clear FIFO like other 'Clear ATN'?*/
! 1974: iha_set_ssig(iot, ioh, REQ | BSY | SEL | ATN, 0);
! 1975: flags = sc->HCS_ActScb->SCB_Tcs->TCS_Flags;
! 1976: if ((flags & FLAG_NO_NEG_SYNC) == 0)
! 1977: iha_set_ssig(iot, ioh, REQ | BSY | SEL, ATN);
! 1978: phase = iha_wait(sc, iot, ioh, MSG_ACCEPT);
! 1979: break;
! 1980: case MSG_EXTENDED:
! 1981: phase = iha_msgin_extended(sc, iot, ioh);
! 1982: break;
! 1983: case MSG_IGN_WIDE_RESIDUE:
! 1984: phase = iha_msgin_ignore_wid_resid(sc, iot, ioh);
! 1985: break;
! 1986: case MSG_CMDCOMPLETE:
! 1987: sc->HCS_Flags |= FLAG_EXPECT_DONE_DISC;
! 1988: bus_space_write_1(iot, ioh, TUL_SCTRL0, RSFIFO);
! 1989: phase = iha_wait(sc, iot, ioh, MSG_ACCEPT);
! 1990: if (phase != -1) {
! 1991: iha_bad_seq(sc);
! 1992: return (-1);
! 1993: }
! 1994: break;
! 1995: default:
! 1996: #ifdef IHA_DEBUG_STATE
! 1997: printf("[debug] iha_msgin: bad msg type: %d\n", msg);
! 1998: #endif
! 1999: phase = iha_msgout_reject(sc, iot, ioh);
! 2000: break;
! 2001: }
! 2002:
! 2003: if (phase != PHASE_MSG_IN)
! 2004: return (phase);
! 2005: }
! 2006: /* NOTREACHED */
! 2007: }
! 2008:
! 2009: int
! 2010: iha_msgin_ignore_wid_resid(sc, iot, ioh)
! 2011: struct iha_softc *sc;
! 2012: bus_space_tag_t iot;
! 2013: bus_space_handle_t ioh;
! 2014: {
! 2015: int phase;
! 2016:
! 2017: phase = iha_wait(sc, iot, ioh, MSG_ACCEPT);
! 2018:
! 2019: if (phase == PHASE_MSG_IN) {
! 2020: phase = iha_wait(sc, iot, ioh, XF_FIFO_IN);
! 2021:
! 2022: if (phase != -1) {
! 2023: bus_space_write_1(iot, ioh, TUL_SFIFO, 0);
! 2024: bus_space_read_1 (iot, ioh, TUL_SFIFO);
! 2025: bus_space_read_1 (iot, ioh, TUL_SFIFO);
! 2026:
! 2027: phase = iha_wait(sc, iot, ioh, MSG_ACCEPT);
! 2028: }
! 2029: }
! 2030:
! 2031: return (phase);
! 2032: }
! 2033:
! 2034: int
! 2035: iha_msgin_extended(sc, iot, ioh)
! 2036: struct iha_softc *sc;
! 2037: bus_space_tag_t iot;
! 2038: bus_space_handle_t ioh;
! 2039: {
! 2040: u_int16_t flags;
! 2041: int i, phase, msglen, msgcode;
! 2042:
! 2043: /* XXX - can we just stop reading and reject, or do we have to
! 2044: * read all input, discarding the excess, and then reject
! 2045: */
! 2046: for (i = 0; i < IHA_MAX_EXTENDED_MSG; i++) {
! 2047: phase = iha_wait(sc, iot, ioh, MSG_ACCEPT);
! 2048:
! 2049: if (phase != PHASE_MSG_IN)
! 2050: return (phase);
! 2051:
! 2052: bus_space_write_4(iot, ioh, TUL_STCNT0, 1);
! 2053:
! 2054: if (iha_wait(sc, iot, ioh, XF_FIFO_IN) == -1)
! 2055: return (-1);
! 2056:
! 2057: sc->HCS_Msg[i] = bus_space_read_1(iot, ioh, TUL_SFIFO);
! 2058:
! 2059: if (sc->HCS_Msg[0] == i)
! 2060: break;
! 2061: }
! 2062:
! 2063: msglen = sc->HCS_Msg[0];
! 2064: msgcode = sc->HCS_Msg[1];
! 2065:
! 2066: if ((msglen == MSG_EXT_SDTR_LEN) && (msgcode == MSG_EXT_SDTR)) {
! 2067: if (iha_msgin_sdtr(sc) == 0) {
! 2068: iha_sync_done(sc, iot, ioh);
! 2069: return (iha_wait(sc, iot, ioh, MSG_ACCEPT));
! 2070: }
! 2071:
! 2072: iha_set_ssig(iot, ioh, REQ | BSY | SEL, ATN);
! 2073:
! 2074: phase = iha_wait(sc, iot, ioh, MSG_ACCEPT);
! 2075: if (phase != PHASE_MSG_OUT)
! 2076: return (phase);
! 2077:
! 2078: /* Clear FIFO for important message - final SYNC offer */
! 2079: bus_space_write_1(iot, ioh, TUL_SCTRL0, RSFIFO);
! 2080:
! 2081: iha_sync_done(sc, iot, ioh); /* This is our final offer */
! 2082:
! 2083: } else if ((msglen == MSG_EXT_WDTR_LEN) && (msgcode == MSG_EXT_WDTR)) {
! 2084:
! 2085: flags = sc->HCS_ActScb->SCB_Tcs->TCS_Flags;
! 2086:
! 2087: if ((flags & FLAG_NO_WIDE) != 0)
! 2088: /* Offer 8 bit xfers only */
! 2089: sc->HCS_Msg[2] = MSG_EXT_WDTR_BUS_8_BIT;
! 2090:
! 2091: else if (sc->HCS_Msg[2] > MSG_EXT_WDTR_BUS_32_BIT)
! 2092: return (iha_msgout_reject(sc, iot, ioh));
! 2093:
! 2094: else if (sc->HCS_Msg[2] == MSG_EXT_WDTR_BUS_32_BIT)
! 2095: /* Offer 16 instead */
! 2096: sc->HCS_Msg[2] = MSG_EXT_WDTR_BUS_32_BIT;
! 2097:
! 2098: else {
! 2099: iha_wide_done(sc, iot, ioh);
! 2100: if ((flags & FLAG_NO_NEG_SYNC) == 0)
! 2101: iha_set_ssig(iot, ioh, REQ | BSY | SEL, ATN);
! 2102: return (iha_wait(sc, iot, ioh, MSG_ACCEPT));
! 2103: }
! 2104:
! 2105: iha_set_ssig(iot, ioh, REQ | BSY | SEL, ATN);
! 2106:
! 2107: phase = iha_wait(sc, iot, ioh, MSG_ACCEPT);
! 2108: if (phase != PHASE_MSG_OUT)
! 2109: return (phase);
! 2110:
! 2111: } else
! 2112: return (iha_msgout_reject(sc, iot, ioh));
! 2113:
! 2114: /* Send message built in sc->HCS_Msg[] */
! 2115: return (iha_msgout_extended(sc, iot, ioh));
! 2116: }
! 2117:
! 2118: /*
! 2119: * iha_msgin_sdtr - check SDTR msg in HCS_Msg. If the offer is
! 2120: * acceptable leave HCS_Msg as is and return 0.
! 2121: * If the negotiation must continue, modify HCS_Msg
! 2122: * as needed and return 1. Else return 0.
! 2123: */
! 2124: int
! 2125: iha_msgin_sdtr(sc)
! 2126: struct iha_softc *sc;
! 2127: {
! 2128: u_int16_t flags;
! 2129: u_int8_t default_period;
! 2130: int newoffer;
! 2131:
! 2132: flags = sc->HCS_ActScb->SCB_Tcs->TCS_Flags;
! 2133:
! 2134: default_period = iha_rate_tbl[flags & FLAG_SCSI_RATE];
! 2135:
! 2136: if (sc->HCS_Msg[3] == 0) /* target offered async only. Accept it. */
! 2137: return (0);
! 2138:
! 2139: newoffer = 0;
! 2140:
! 2141: if ((flags & FLAG_NO_SYNC) != 0) {
! 2142: sc->HCS_Msg[3] = 0;
! 2143: newoffer = 1;
! 2144: }
! 2145:
! 2146: if (sc->HCS_Msg[3] > IHA_MAX_TARGETS-1) {
! 2147: sc->HCS_Msg[3] = IHA_MAX_TARGETS-1;
! 2148: newoffer = 1;
! 2149: }
! 2150:
! 2151: if (sc->HCS_Msg[2] < default_period) {
! 2152: sc->HCS_Msg[2] = default_period;
! 2153: newoffer = 1;
! 2154: }
! 2155:
! 2156: if (sc->HCS_Msg[2] >= 59) {
! 2157: sc->HCS_Msg[3] = 0;
! 2158: newoffer = 1;
! 2159: }
! 2160:
! 2161: return (newoffer);
! 2162: }
! 2163:
! 2164: int
! 2165: iha_msgout(sc, iot, ioh, msg)
! 2166: struct iha_softc *sc;
! 2167: bus_space_tag_t iot;
! 2168: bus_space_handle_t ioh;
! 2169: u_int8_t msg;
! 2170: {
! 2171: bus_space_write_1(iot, ioh, TUL_SFIFO, msg);
! 2172:
! 2173: return (iha_wait(sc, iot, ioh, XF_FIFO_OUT));
! 2174: }
! 2175:
! 2176: void
! 2177: iha_msgout_abort(sc, iot, ioh, aborttype)
! 2178: struct iha_softc *sc;
! 2179: bus_space_tag_t iot;
! 2180: bus_space_handle_t ioh;
! 2181: u_int8_t aborttype;
! 2182: {
! 2183: iha_set_ssig(iot, ioh, REQ | BSY | SEL, ATN);
! 2184:
! 2185: switch (iha_wait(sc, iot, ioh, MSG_ACCEPT)) {
! 2186: case -1:
! 2187: break;
! 2188:
! 2189: case PHASE_MSG_OUT:
! 2190: sc->HCS_Flags |= FLAG_EXPECT_DISC;
! 2191: if (iha_msgout(sc, iot, ioh, aborttype) != -1)
! 2192: iha_bad_seq(sc);
! 2193: break;
! 2194:
! 2195: default:
! 2196: iha_bad_seq(sc);
! 2197: break;
! 2198: }
! 2199: }
! 2200:
! 2201: int
! 2202: iha_msgout_reject(sc, iot, ioh)
! 2203: struct iha_softc *sc;
! 2204: bus_space_tag_t iot;
! 2205: bus_space_handle_t ioh;
! 2206: {
! 2207: iha_set_ssig(iot, ioh, REQ | BSY | SEL, ATN);
! 2208:
! 2209: if (iha_wait(sc, iot, ioh, MSG_ACCEPT) == PHASE_MSG_OUT)
! 2210: return (iha_msgout(sc, iot, ioh, MSG_MESSAGE_REJECT));
! 2211:
! 2212: return (-1);
! 2213: }
! 2214:
! 2215: int
! 2216: iha_msgout_extended(sc, iot, ioh)
! 2217: struct iha_softc *sc;
! 2218: bus_space_tag_t iot;
! 2219: bus_space_handle_t ioh;
! 2220: {
! 2221: int phase;
! 2222:
! 2223: bus_space_write_1(iot, ioh, TUL_SFIFO, MSG_EXTENDED);
! 2224:
! 2225: bus_space_write_multi_1(iot, ioh, TUL_SFIFO,
! 2226: sc->HCS_Msg, sc->HCS_Msg[0]+1);
! 2227:
! 2228: phase = iha_wait(sc, iot, ioh, XF_FIFO_OUT);
! 2229:
! 2230: bus_space_write_1(iot, ioh, TUL_SCTRL0, RSFIFO);
! 2231: iha_set_ssig(iot, ioh, REQ | BSY | SEL | ATN, 0);
! 2232:
! 2233: return (phase);
! 2234: }
! 2235:
! 2236: int
! 2237: iha_msgout_wdtr(sc, iot, ioh)
! 2238: struct iha_softc *sc;
! 2239: bus_space_tag_t iot;
! 2240: bus_space_handle_t ioh;
! 2241: {
! 2242: sc->HCS_ActScb->SCB_Tcs->TCS_Flags |= FLAG_WIDE_DONE;
! 2243:
! 2244: sc->HCS_Msg[0] = MSG_EXT_WDTR_LEN;
! 2245: sc->HCS_Msg[1] = MSG_EXT_WDTR;
! 2246: sc->HCS_Msg[2] = MSG_EXT_WDTR_BUS_16_BIT;
! 2247:
! 2248: return (iha_msgout_extended(sc, iot, ioh));
! 2249: }
! 2250:
! 2251: int
! 2252: iha_msgout_sdtr(sc, iot, ioh)
! 2253: struct iha_softc *sc;
! 2254: bus_space_tag_t iot;
! 2255: bus_space_handle_t ioh;
! 2256: {
! 2257: u_int16_t rateindex;
! 2258: u_int8_t sync_rate;
! 2259:
! 2260: rateindex = sc->HCS_ActScb->SCB_Tcs->TCS_Flags & FLAG_SCSI_RATE;
! 2261:
! 2262: sync_rate = iha_rate_tbl[rateindex];
! 2263:
! 2264: sc->HCS_Msg[0] = MSG_EXT_SDTR_LEN;
! 2265: sc->HCS_Msg[1] = MSG_EXT_SDTR;
! 2266: sc->HCS_Msg[2] = sync_rate;
! 2267: sc->HCS_Msg[3] = IHA_MAX_TARGETS-1; /* REQ/ACK */
! 2268:
! 2269: return (iha_msgout_extended(sc, iot, ioh));
! 2270: }
! 2271:
! 2272: void
! 2273: iha_wide_done(sc, iot, ioh)
! 2274: struct iha_softc *sc;
! 2275: bus_space_tag_t iot;
! 2276: bus_space_handle_t ioh;
! 2277: {
! 2278: struct tcs *pTcs = sc->HCS_ActScb->SCB_Tcs;
! 2279:
! 2280: pTcs->TCS_JS_Period = 0;
! 2281:
! 2282: if (sc->HCS_Msg[2] != 0)
! 2283: pTcs->TCS_JS_Period |= PERIOD_WIDE_SCSI;
! 2284:
! 2285: pTcs->TCS_SConfig0 &= ~ALTPD;
! 2286: pTcs->TCS_Flags &= ~FLAG_SYNC_DONE;
! 2287: pTcs->TCS_Flags |= FLAG_WIDE_DONE;
! 2288:
! 2289: bus_space_write_1(iot, ioh, TUL_SCONFIG0, pTcs->TCS_SConfig0);
! 2290: bus_space_write_1(iot, ioh, TUL_SYNCM, pTcs->TCS_JS_Period);
! 2291: }
! 2292:
! 2293: void
! 2294: iha_sync_done(sc, iot, ioh)
! 2295: struct iha_softc *sc;
! 2296: bus_space_tag_t iot;
! 2297: bus_space_handle_t ioh;
! 2298: {
! 2299: struct tcs *pTcs = sc->HCS_ActScb->SCB_Tcs;
! 2300: int i;
! 2301:
! 2302: if ((pTcs->TCS_Flags & FLAG_SYNC_DONE) == 0) {
! 2303: if (sc->HCS_Msg[3] != 0) {
! 2304: pTcs->TCS_JS_Period |= sc->HCS_Msg[3];
! 2305:
! 2306: /* pick the highest possible rate */
! 2307: for (i = 0; i < sizeof(iha_rate_tbl); i++)
! 2308: if (iha_rate_tbl[i] >= sc->HCS_Msg[2])
! 2309: break;
! 2310:
! 2311: pTcs->TCS_JS_Period |= (i << 4);
! 2312: pTcs->TCS_SConfig0 |= ALTPD;
! 2313: }
! 2314:
! 2315: pTcs->TCS_Flags |= FLAG_SYNC_DONE;
! 2316:
! 2317: bus_space_write_1(iot, ioh, TUL_SCONFIG0, pTcs->TCS_SConfig0);
! 2318: bus_space_write_1(iot, ioh, TUL_SYNCM, pTcs->TCS_JS_Period);
! 2319: }
! 2320: }
! 2321:
! 2322: void
! 2323: iha_reset_chip(sc, iot, ioh)
! 2324: struct iha_softc *sc;
! 2325: bus_space_tag_t iot;
! 2326: bus_space_handle_t ioh;
! 2327: {
! 2328: int i;
! 2329:
! 2330: /* reset tulip chip */
! 2331:
! 2332: bus_space_write_1(iot, ioh, TUL_SCTRL0, RSCSI);
! 2333:
! 2334: do
! 2335: sc->HCS_JSInt = bus_space_read_1(iot, ioh, TUL_SISTAT);
! 2336: while((sc->HCS_JSInt & SRSTD) == 0);
! 2337:
! 2338: iha_set_ssig(iot, ioh, 0, 0);
! 2339:
! 2340: /*
! 2341: * Stall for 2 seconds, wait for target's firmware ready.
! 2342: */
! 2343: for (i = 0; i < 2000; i++)
! 2344: DELAY (1000);
! 2345:
! 2346: bus_space_read_1(iot, ioh, TUL_SISTAT); /* Clear any active interrupt*/
! 2347: }
! 2348:
! 2349: void
! 2350: iha_select(sc, iot, ioh, pScb, select_type)
! 2351: struct iha_softc *sc;
! 2352: bus_space_tag_t iot;
! 2353: bus_space_handle_t ioh;
! 2354: struct iha_scb *pScb;
! 2355: u_int8_t select_type;
! 2356: {
! 2357: int s;
! 2358:
! 2359: switch (select_type) {
! 2360: case SEL_ATN:
! 2361: bus_space_write_1(iot, ioh, TUL_SFIFO, pScb->SCB_Ident);
! 2362: bus_space_write_multi_1(iot, ioh, TUL_SFIFO,
! 2363: pScb->SCB_CDB, pScb->SCB_CDBLen);
! 2364:
! 2365: pScb->SCB_NxtStat = 2;
! 2366: break;
! 2367:
! 2368: case SELATNSTOP:
! 2369: pScb->SCB_NxtStat = 1;
! 2370: break;
! 2371:
! 2372: case SEL_ATN3:
! 2373: bus_space_write_1(iot, ioh, TUL_SFIFO, pScb->SCB_Ident);
! 2374: bus_space_write_1(iot, ioh, TUL_SFIFO, pScb->SCB_TagMsg);
! 2375: bus_space_write_1(iot, ioh, TUL_SFIFO, pScb->SCB_TagId);
! 2376:
! 2377: bus_space_write_multi_1(iot, ioh, TUL_SFIFO, pScb->SCB_CDB,
! 2378: pScb->SCB_CDBLen);
! 2379:
! 2380: pScb->SCB_NxtStat = 2;
! 2381: break;
! 2382:
! 2383: default:
! 2384: #ifdef IHA_DEBUG_STATE
! 2385: sc_print_addr(pScb->SCB_Xs->sc_link);
! 2386: printf("[debug] iha_select() - unknown select type = 0x%02x\n",
! 2387: select_type);
! 2388: #endif
! 2389: return;
! 2390: }
! 2391:
! 2392: s = splbio();
! 2393: TAILQ_REMOVE(&sc->HCS_PendScb, pScb, SCB_ScbList);
! 2394: splx(s);
! 2395:
! 2396: pScb->SCB_Status = STATUS_SELECT;
! 2397:
! 2398: sc->HCS_ActScb = pScb;
! 2399:
! 2400: bus_space_write_1(iot, ioh, TUL_SCMD, select_type);
! 2401: }
! 2402:
! 2403: /*
! 2404: * iha_wait - wait for an interrupt to service or a SCSI bus phase change
! 2405: * after writing the supplied command to the tulip chip. If
! 2406: * the command is NO_OP, skip the command writing.
! 2407: */
! 2408: int
! 2409: iha_wait(sc, iot, ioh, cmd)
! 2410: struct iha_softc *sc;
! 2411: bus_space_tag_t iot;
! 2412: bus_space_handle_t ioh;
! 2413: u_int8_t cmd;
! 2414: {
! 2415: if (cmd != NO_OP)
! 2416: bus_space_write_1(iot, ioh, TUL_SCMD, cmd);
! 2417:
! 2418: /*
! 2419: * Have to do this here, in addition to in iha_isr, because
! 2420: * interrupts might be turned off when we get here.
! 2421: */
! 2422: do
! 2423: sc->HCS_JSStatus0 = bus_space_read_1(iot, ioh, TUL_STAT0);
! 2424: while ((sc->HCS_JSStatus0 & INTPD) == 0);
! 2425:
! 2426: sc->HCS_JSStatus1 = bus_space_read_1(iot, ioh, TUL_STAT1);
! 2427: sc->HCS_JSInt = bus_space_read_1(iot, ioh, TUL_SISTAT);
! 2428:
! 2429: sc->HCS_Phase = sc->HCS_JSStatus0 & PH_MASK;
! 2430:
! 2431: if ((sc->HCS_JSInt & SRSTD) != 0) {
! 2432: /* SCSI bus reset interrupt */
! 2433: iha_reset_scsi_bus(sc);
! 2434: return (-1);
! 2435: }
! 2436:
! 2437: if ((sc->HCS_JSInt & RSELED) != 0)
! 2438: /* Reselection interrupt */
! 2439: return (iha_resel(sc, iot, ioh));
! 2440:
! 2441: if ((sc->HCS_JSInt & STIMEO) != 0) {
! 2442: /* selected/reselected timeout interrupt */
! 2443: iha_busfree(sc, iot, ioh);
! 2444: return (-1);
! 2445: }
! 2446:
! 2447: if ((sc->HCS_JSInt & DISCD) != 0) {
! 2448: /* BUS disconnection interrupt */
! 2449: if ((sc->HCS_Flags & FLAG_EXPECT_DONE_DISC) != 0) {
! 2450: bus_space_write_1(iot, ioh, TUL_SCTRL0, RSFIFO);
! 2451: bus_space_write_1(iot, ioh, TUL_SCONFIG0,
! 2452: SCONFIG0DEFAULT);
! 2453: bus_space_write_1(iot, ioh, TUL_SCTRL1, EHRSL);
! 2454: iha_append_done_scb(sc, sc->HCS_ActScb, HOST_OK);
! 2455: sc->HCS_Flags &= ~FLAG_EXPECT_DONE_DISC;
! 2456:
! 2457: } else if ((sc->HCS_Flags & FLAG_EXPECT_DISC) != 0) {
! 2458: bus_space_write_1(iot, ioh, TUL_SCTRL0, RSFIFO);
! 2459: bus_space_write_1(iot, ioh, TUL_SCONFIG0,
! 2460: SCONFIG0DEFAULT);
! 2461: bus_space_write_1(iot, ioh, TUL_SCTRL1, EHRSL);
! 2462: sc->HCS_ActScb = NULL;
! 2463: sc->HCS_Flags &= ~FLAG_EXPECT_DISC;
! 2464:
! 2465: } else
! 2466: iha_busfree(sc, iot, ioh);
! 2467:
! 2468: return (-1);
! 2469: }
! 2470:
! 2471: return (sc->HCS_Phase);
! 2472: }
! 2473:
! 2474: /*
! 2475: * iha_done_scb - We have a scb which has been processed by the
! 2476: * adaptor, now we look to see how the operation went.
! 2477: */
! 2478: void
! 2479: iha_done_scb(sc, pScb)
! 2480: struct iha_softc *sc;
! 2481: struct iha_scb *pScb;
! 2482: {
! 2483: struct scsi_sense_data *s1, *s2;
! 2484: struct scsi_xfer *xs = pScb->SCB_Xs;
! 2485:
! 2486: if (xs != NULL) {
! 2487: timeout_del(&xs->stimeout);
! 2488:
! 2489: xs->status = pScb->SCB_TaStat;
! 2490:
! 2491: if ((pScb->SCB_Flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) != 0) {
! 2492: bus_dmamap_sync(sc->sc_dmat, pScb->SCB_DataDma,
! 2493: 0, pScb->SCB_BufChars,
! 2494: ((pScb->SCB_Flags & SCSI_DATA_IN) ?
! 2495: BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE));
! 2496: bus_dmamap_unload(sc->sc_dmat, pScb->SCB_DataDma);
! 2497: }
! 2498: if ((pScb->SCB_Flags & FLAG_SG) != 0) {
! 2499: bus_dmamap_sync(sc->sc_dmat, pScb->SCB_SGDma,
! 2500: 0, sizeof(pScb->SCB_SGList),
! 2501: BUS_DMASYNC_POSTWRITE);
! 2502: bus_dmamap_unload(sc->sc_dmat, pScb->SCB_SGDma);
! 2503: }
! 2504:
! 2505: switch (pScb->SCB_HaStat) {
! 2506: case HOST_OK:
! 2507: switch (pScb->SCB_TaStat) {
! 2508: case SCSI_OK:
! 2509: case SCSI_COND_MET:
! 2510: case SCSI_INTERM:
! 2511: case SCSI_INTERM_COND_MET:
! 2512: xs->resid = pScb->SCB_BufCharsLeft;
! 2513: xs->error = XS_NOERROR;
! 2514: break;
! 2515:
! 2516: case SCSI_RESV_CONFLICT:
! 2517: case SCSI_BUSY:
! 2518: case SCSI_QUEUE_FULL:
! 2519: xs->error = XS_BUSY;
! 2520: break;
! 2521:
! 2522: case SCSI_TERMINATED:
! 2523: case SCSI_ACA_ACTIVE:
! 2524: case SCSI_CHECK:
! 2525: s1 = &pScb->SCB_ScsiSenseData;
! 2526: s2 = &xs->sense;
! 2527: *s2 = *s1;
! 2528:
! 2529: xs->error = XS_SENSE;
! 2530: break;
! 2531:
! 2532: default:
! 2533: xs->error = XS_DRIVER_STUFFUP;
! 2534: break;
! 2535: }
! 2536: break;
! 2537:
! 2538: case HOST_SEL_TOUT:
! 2539: xs->error = XS_SELTIMEOUT;
! 2540: break;
! 2541:
! 2542: case HOST_SCSI_RST:
! 2543: case HOST_DEV_RST:
! 2544: xs->error = XS_RESET;
! 2545: break;
! 2546:
! 2547: case HOST_SPERR:
! 2548: sc_print_addr(xs->sc_link);
! 2549: printf("SCSI Parity error detected\n");
! 2550: xs->error = XS_DRIVER_STUFFUP;
! 2551: break;
! 2552:
! 2553: case HOST_TIMED_OUT:
! 2554: xs->error = XS_TIMEOUT;
! 2555: break;
! 2556:
! 2557: case HOST_DO_DU:
! 2558: case HOST_BAD_PHAS:
! 2559: default:
! 2560: xs->error = XS_DRIVER_STUFFUP;
! 2561: break;
! 2562: }
! 2563:
! 2564: xs->flags |= ITSDONE;
! 2565: scsi_done(xs);
! 2566: }
! 2567:
! 2568: iha_append_free_scb(sc, pScb);
! 2569: }
! 2570:
! 2571: void
! 2572: iha_timeout(arg)
! 2573: void *arg;
! 2574: {
! 2575: struct iha_scb *pScb = (struct iha_scb *)arg;
! 2576: struct scsi_xfer *xs = pScb->SCB_Xs;
! 2577:
! 2578: if (xs != NULL) {
! 2579: sc_print_addr(xs->sc_link);
! 2580: printf("SCSI OpCode 0x%02x timed out\n", xs->cmd->opcode);
! 2581: iha_abort_xs(xs->sc_link->adapter_softc, xs, HOST_TIMED_OUT);
! 2582: }
! 2583: }
! 2584:
! 2585: void
! 2586: iha_exec_scb(sc, pScb)
! 2587: struct iha_softc *sc;
! 2588: struct iha_scb *pScb;
! 2589: {
! 2590: bus_space_handle_t ioh;
! 2591: bus_space_tag_t iot;
! 2592: int s;
! 2593:
! 2594: s = splbio();
! 2595:
! 2596: if (((pScb->SCB_Flags & SCSI_RESET) != 0)
! 2597: || (pScb->SCB_CDB[0] == REQUEST_SENSE))
! 2598: iha_push_pend_scb(sc, pScb); /* Insert SCB at head of Pend */
! 2599: else
! 2600: iha_append_pend_scb(sc, pScb); /* Append SCB to tail of Pend */
! 2601:
! 2602: /*
! 2603: * Run through iha_main() to ensure something is active, if
! 2604: * only this new SCB.
! 2605: */
! 2606: if (sc->HCS_Semaph != SEMAPH_IN_MAIN) {
! 2607: iot = sc->sc_iot;
! 2608: ioh = sc->sc_ioh;
! 2609:
! 2610: bus_space_write_1(iot, ioh, TUL_IMSK, MASK_ALL);
! 2611: sc->HCS_Semaph = SEMAPH_IN_MAIN;
! 2612:
! 2613: splx(s);
! 2614: iha_main(sc, iot, ioh);
! 2615: s = splbio();
! 2616:
! 2617: sc->HCS_Semaph = ~SEMAPH_IN_MAIN;
! 2618: bus_space_write_1(iot, ioh, TUL_IMSK, (MASK_ALL & ~MSCMP));
! 2619: }
! 2620:
! 2621: splx(s);
! 2622: }
! 2623:
! 2624:
! 2625: /*
! 2626: * iha_set_ssig - read the current scsi signal mask, then write a new
! 2627: * one which turns off/on the specified signals.
! 2628: */
! 2629: void
! 2630: iha_set_ssig( iot, ioh, offsigs, onsigs)
! 2631: bus_space_tag_t iot;
! 2632: bus_space_handle_t ioh;
! 2633: u_int8_t offsigs, onsigs;
! 2634: {
! 2635: u_int8_t currsigs;
! 2636:
! 2637: currsigs = bus_space_read_1(iot, ioh, TUL_SSIGI);
! 2638: bus_space_write_1(iot, ioh, TUL_SSIGO, (currsigs & ~offsigs) | onsigs);
! 2639: }
! 2640:
! 2641: void
! 2642: iha_print_info(sc, target)
! 2643: struct iha_softc *sc;
! 2644: int target;
! 2645: {
! 2646: u_int8_t period = sc->HCS_Tcs[target].TCS_JS_Period;
! 2647: u_int8_t config = sc->HCS_Tcs[target].TCS_SConfig0;
! 2648: int rate;
! 2649:
! 2650: printf("%s: target %d using %d bit ", sc->sc_dev.dv_xname, target,
! 2651: (period & PERIOD_WIDE_SCSI) ? 16 : 8);
! 2652:
! 2653: if ((period & PERIOD_SYOFS) == 0)
! 2654: printf("async ");
! 2655: else {
! 2656: rate = (period & PERIOD_SYXPD) >> 4;
! 2657: if ((config & ALTPD) == 0)
! 2658: rate = 100 + rate * 50;
! 2659: else
! 2660: rate = 50 + rate * 25;
! 2661: rate = 1000000000 / rate;
! 2662: printf("%d.%d MHz %d REQ/ACK offset ", rate / 1000000,
! 2663: (rate % 1000000 + 99999) / 100000, period & PERIOD_SYOFS);
! 2664: }
! 2665:
! 2666: printf("xfers\n");
! 2667: }
! 2668:
! 2669:
! 2670: /*
! 2671: * iha_alloc_scbs - allocate and map the SCB's for the supplied iha_softc
! 2672: */
! 2673: int
! 2674: iha_alloc_scbs(sc)
! 2675: struct iha_softc *sc;
! 2676: {
! 2677: bus_dma_segment_t seg;
! 2678: int error, rseg;
! 2679:
! 2680: /*
! 2681: * Allocate dma-safe memory for the SCB's
! 2682: */
! 2683: if ((error = bus_dmamem_alloc(sc->sc_dmat,
! 2684: sizeof(struct iha_scb)*IHA_MAX_SCB,
! 2685: NBPG, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT))
! 2686: != 0) {
! 2687: printf("%s: unable to allocate SCBs,"
! 2688: " error = %d\n", sc->sc_dev.dv_xname, error);
! 2689: return (error);
! 2690: }
! 2691: if ((error = bus_dmamem_map(sc->sc_dmat,
! 2692: &seg, rseg, sizeof(struct iha_scb)*IHA_MAX_SCB,
! 2693: (caddr_t *)&sc->HCS_Scb, BUS_DMA_NOWAIT | BUS_DMA_COHERENT))
! 2694: != 0) {
! 2695: printf("%s: unable to map SCBs, error = %d\n",
! 2696: sc->sc_dev.dv_xname, error);
! 2697: return (error);
! 2698: }
! 2699: bzero(sc->HCS_Scb, sizeof(struct iha_scb)*IHA_MAX_SCB);
! 2700:
! 2701: return (0);
! 2702: }
! 2703:
! 2704: /*
! 2705: * iha_read_eeprom - read contents of serial EEPROM into iha_nvram pointed at
! 2706: * by parameter nvram.
! 2707: */
! 2708: void
! 2709: iha_read_eeprom(iot, ioh, nvram)
! 2710: bus_space_tag_t iot;
! 2711: bus_space_handle_t ioh;
! 2712: struct iha_nvram *nvram;
! 2713: {
! 2714: u_int32_t chksum;
! 2715: u_int16_t *np;
! 2716: u_int8_t gctrl, addr;
! 2717:
! 2718: const int chksum_addr = offsetof(struct iha_nvram, NVM_CheckSum) / 2;
! 2719:
! 2720: /* Enable EEProm programming */
! 2721: gctrl = bus_space_read_1(iot, ioh, TUL_GCTRL0) | EEPRG;
! 2722: bus_space_write_1(iot, ioh, TUL_GCTRL0, gctrl);
! 2723:
! 2724: /* Read EEProm */
! 2725: np = (u_int16_t *)nvram;
! 2726: for (addr=0, chksum=0; addr < chksum_addr; addr++, np++) {
! 2727: *np = iha_se2_rd(iot, ioh, addr);
! 2728: chksum += *np;
! 2729: }
! 2730:
! 2731: chksum &= 0x0000ffff;
! 2732: nvram->NVM_CheckSum = iha_se2_rd(iot, ioh, chksum_addr);
! 2733:
! 2734: /* Disable EEProm programming */
! 2735: gctrl = bus_space_read_1(iot, ioh, TUL_GCTRL0) & ~EEPRG;
! 2736: bus_space_write_1(iot, ioh, TUL_GCTRL0, gctrl);
! 2737:
! 2738: if ((nvram->NVM_Signature != SIGNATURE)
! 2739: ||
! 2740: (nvram->NVM_CheckSum != chksum))
! 2741: panic("iha: invalid EEPROM, bad signature or checksum");
! 2742: }
! 2743:
! 2744: /*
! 2745: * iha_se2_rd - read & return the 16 bit value at the specified
! 2746: * offset in the Serial E2PROM
! 2747: *
! 2748: */
! 2749: u_int16_t
! 2750: iha_se2_rd(iot, ioh, addr)
! 2751: bus_space_tag_t iot;
! 2752: bus_space_handle_t ioh;
! 2753: u_int8_t addr;
! 2754: {
! 2755: u_int16_t readWord;
! 2756: u_int8_t bit;
! 2757: int i;
! 2758:
! 2759: /* Send 'READ' instruction == address | READ bit */
! 2760: iha_se2_instr(iot, ioh, (addr | NVREAD));
! 2761:
! 2762: readWord = 0;
! 2763: for (i = 15; i >= 0; i--) {
! 2764: bus_space_write_1(iot, ioh, TUL_NVRAM, NVRCS | NVRCK);
! 2765: DELAY(5);
! 2766:
! 2767: bus_space_write_1(iot, ioh, TUL_NVRAM, NVRCS);
! 2768: DELAY(5);
! 2769:
! 2770: /* sample data after the following edge of clock */
! 2771: bit = bus_space_read_1(iot, ioh, TUL_NVRAM) & NVRDI;
! 2772: DELAY(5);
! 2773:
! 2774: readWord += bit << i;
! 2775: }
! 2776:
! 2777: bus_space_write_1(iot, ioh, TUL_NVRAM, 0);
! 2778: DELAY(5);
! 2779:
! 2780: return (readWord);
! 2781: }
! 2782:
! 2783: /*
! 2784: * iha_se2_instr - write an octet to serial E2PROM one bit at a time
! 2785: */
! 2786: void
! 2787: iha_se2_instr(iot, ioh, instr)
! 2788: bus_space_tag_t iot;
! 2789: bus_space_handle_t ioh;
! 2790: u_int8_t instr;
! 2791: {
! 2792: u_int8_t b;
! 2793: int i;
! 2794:
! 2795: b = NVRCS | NVRDO; /* Write the start bit (== 1) */
! 2796:
! 2797: bus_space_write_1(iot, ioh, TUL_NVRAM, b);
! 2798: DELAY(5);
! 2799: bus_space_write_1(iot, ioh, TUL_NVRAM, b | NVRCK);
! 2800: DELAY(5);
! 2801:
! 2802: for (i = 0; i < 8; i++, instr <<= 1) {
! 2803: if (instr & 0x80)
! 2804: b = NVRCS | NVRDO; /* Write a 1 bit */
! 2805: else
! 2806: b = NVRCS; /* Write a 0 bit */
! 2807:
! 2808: bus_space_write_1(iot, ioh, TUL_NVRAM, b);
! 2809: DELAY(5);
! 2810: bus_space_write_1(iot, ioh, TUL_NVRAM, b | NVRCK);
! 2811: DELAY(5);
! 2812: }
! 2813:
! 2814: bus_space_write_1(iot, ioh, TUL_NVRAM, NVRCS);
! 2815: DELAY(5);
! 2816:
! 2817: return;
! 2818: }
! 2819:
! 2820: /*
! 2821: * iha_reset_tcs - reset the target control structure pointed
! 2822: * to by pTcs to default values. TCS_Flags
! 2823: * only has the negotiation done bits reset as
! 2824: * the other bits are fixed at initialization.
! 2825: */
! 2826: void
! 2827: iha_reset_tcs(pTcs, config0)
! 2828: struct tcs *pTcs;
! 2829: u_int8_t config0;
! 2830: {
! 2831: pTcs->TCS_Flags &= ~(FLAG_SYNC_DONE | FLAG_WIDE_DONE);
! 2832: pTcs->TCS_JS_Period = 0;
! 2833: pTcs->TCS_SConfig0 = config0;
! 2834: pTcs->TCS_TagCnt = 0;
! 2835: pTcs->TCS_NonTagScb = NULL;
! 2836: }
CVSweb