1 1.16 thorpej /* $NetBSD: sii.c,v 1.16 2021/08/07 16:19:02 thorpej Exp $ */ 2 1.2 ad 3 1.2 ad /*- 4 1.2 ad * Copyright (c) 1992, 1993 5 1.2 ad * The Regents of the University of California. All rights reserved. 6 1.2 ad * 7 1.2 ad * This code is derived from software contributed to Berkeley by 8 1.2 ad * Ralph Campbell and Rick Macklem. 9 1.2 ad * 10 1.2 ad * Redistribution and use in source and binary forms, with or without 11 1.2 ad * modification, are permitted provided that the following conditions 12 1.2 ad * are met: 13 1.2 ad * 1. Redistributions of source code must retain the above copyright 14 1.2 ad * notice, this list of conditions and the following disclaimer. 15 1.2 ad * 2. Redistributions in binary form must reproduce the above copyright 16 1.2 ad * notice, this list of conditions and the following disclaimer in the 17 1.2 ad * documentation and/or other materials provided with the distribution. 18 1.2 ad * 3. Neither the name of the University nor the names of its contributors 19 1.2 ad * may be used to endorse or promote products derived from this software 20 1.2 ad * without specific prior written permission. 21 1.2 ad * 22 1.2 ad * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 1.2 ad * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.2 ad * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.2 ad * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 1.2 ad * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 1.2 ad * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 1.2 ad * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 1.2 ad * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 1.2 ad * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 1.2 ad * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 1.2 ad * SUCH DAMAGE. 33 1.2 ad * 34 1.2 ad * @(#)sii.c 8.2 (Berkeley) 11/30/93 35 1.2 ad * 36 1.2 ad * from: Header: /sprite/src/kernel/dev/ds3100.md/RCS/devSII.c, 37 1.2 ad * v 9.2 89/09/14 13:37:41 jhh Exp $ SPRITE (DECWRL)"; 38 1.2 ad */ 39 1.2 ad 40 1.2 ad #include <sys/cdefs.h> 41 1.16 thorpej __KERNEL_RCSID(0, "$NetBSD: sii.c,v 1.16 2021/08/07 16:19:02 thorpej Exp $"); 42 1.2 ad 43 1.2 ad #include "sii.h" 44 1.2 ad /* 45 1.2 ad * SCSI interface driver 46 1.2 ad */ 47 1.2 ad #include <sys/param.h> 48 1.2 ad #include <sys/buf.h> 49 1.2 ad #include <sys/conf.h> 50 1.2 ad #include <sys/device.h> 51 1.2 ad #include <sys/systm.h> 52 1.2 ad 53 1.10 matt #include <mips/locore.h> 54 1.2 ad 55 1.2 ad #include <dev/scsipi/scsi_all.h> 56 1.2 ad #include <dev/scsipi/scsi_message.h> 57 1.2 ad #include <dev/scsipi/scsipi_all.h> 58 1.2 ad #include <dev/scsipi/scsipi_disk.h> 59 1.2 ad #include <dev/scsipi/scsiconf.h> 60 1.2 ad 61 1.2 ad /* old 4.4BSD/pmax scsi drivers */ 62 1.2 ad #include <pmax/ibus/siireg.h> /* device registers */ 63 1.2 ad #include <pmax/ibus/siivar.h> /* softc and prototypes */ 64 1.2 ad 65 1.2 ad #include <pmax/pmax/machdep.h> /* prom_scsiid prototype */ 66 1.2 ad 67 1.2 ad /* XXX not in dev/scsipi/scsi_message.h */ 68 1.2 ad #define MSG_EXT_MODIFY_DATA_PTR 0x00 69 1.2 ad 70 1.2 ad extern struct cfdriver sii_cd; 71 1.2 ad 72 1.2 ad /* 73 1.2 ad * MACROS for timing out spin loops. 74 1.2 ad * 75 1.2 ad * Wait until expression is true. 76 1.2 ad * 77 1.2 ad * Control register bits can change at any time so when the CPU 78 1.2 ad * reads a register, the bits might change and 79 1.2 ad * invalidate the setup and hold times for the CPU. 80 1.2 ad * This macro reads the register twice to be sure the value is stable. 81 1.2 ad * 82 1.2 ad * args: var - variable to save control register contents 83 1.2 ad * reg - control register to read 84 1.2 ad * expr - expression to spin on 85 1.2 ad * spincount - maximum number of times through the loop 86 1.2 ad * cntr - variable for number of tries 87 1.2 ad */ 88 1.2 ad #define SII_WAIT_UNTIL(var, reg, expr, spincount, cntr) { \ 89 1.2 ad u_int tmp = reg; \ 90 1.2 ad for (cntr = 0; cntr < spincount; cntr++) { \ 91 1.2 ad while (tmp != (var = reg)) \ 92 1.2 ad tmp = var; \ 93 1.2 ad if (expr) \ 94 1.2 ad break; \ 95 1.2 ad if (cntr >= 100) \ 96 1.2 ad DELAY(100); \ 97 1.2 ad } \ 98 1.2 ad } 99 1.2 ad 100 1.2 ad #ifdef DEBUG 101 1.2 ad int sii_debug = 1; 102 1.2 ad int sii_debug_cmd; 103 1.2 ad int sii_debug_bn; 104 1.2 ad int sii_debug_sz; 105 1.2 ad #define NLOG 16 106 1.2 ad struct sii_log { 107 1.2 ad u_short cstat; 108 1.2 ad u_short dstat; 109 1.2 ad u_short comm; 110 1.2 ad u_short msg; 111 1.2 ad int rlen; 112 1.2 ad int dlen; 113 1.2 ad int target; 114 1.2 ad } sii_log[NLOG], *sii_logp = sii_log; 115 1.2 ad #endif 116 1.2 ad 117 1.2 ad static u_char sii_buf[256]; /* used for extended messages */ 118 1.2 ad 119 1.2 ad #define NORESET 0 120 1.2 ad #define RESET 1 121 1.2 ad #define NOWAIT 0 122 1.2 ad #define WAIT 1 123 1.2 ad 124 1.2 ad 125 1.2 ad /* 126 1.2 ad * Define a safe address in the SCSI buffer for doing status & message DMA 127 1.2 ad * XXX why not add another field to softc? 128 1.2 ad */ 129 1.2 ad #define SII_BUF_ADDR(sc) ((sc)->sc_buf + SII_MAX_DMA_XFER_LENGTH * 14) 130 1.2 ad 131 1.2 ad /* 132 1.2 ad * Forward references 133 1.2 ad */ 134 1.2 ad 135 1.5 dsl static void sii_Reset(struct siisoftc *sc, int resetbus); 136 1.5 dsl static void sii_StartCmd(struct siisoftc *sc, int target); 137 1.5 dsl static void sii_CmdDone(struct siisoftc *sc, int target, int error); 138 1.5 dsl static void sii_DoIntr(struct siisoftc *sc, u_int dstat); 139 1.5 dsl static void sii_StateChg(struct siisoftc *sc, u_int cstat); 140 1.5 dsl static int sii_GetByte(SIIRegs *regs, int phase, int ack); 141 1.5 dsl static void sii_DoSync(SIIRegs *regs, State *state); 142 1.5 dsl static void sii_StartDMA(SIIRegs *regs, int phase, u_short *dmaAddr, 143 1.5 dsl int size); 144 1.2 ad 145 1.2 ad #ifdef DEBUG 146 1.5 dsl static void sii_DumpLog(void); 147 1.2 ad #endif 148 1.2 ad 149 1.2 ad 150 1.2 ad /* 151 1.2 ad * Match driver based on name 152 1.2 ad */ 153 1.2 ad void 154 1.6 dsl siiattach(struct siisoftc *sc) 155 1.2 ad { 156 1.2 ad int i; 157 1.2 ad 158 1.2 ad sc->sc_target = -1; /* no command active */ 159 1.2 ad 160 1.2 ad /* 161 1.2 ad * Give each target its own DMA buffer region. 162 1.2 ad * Make it big enough for 2 max transfers so we can ping pong buffers 163 1.2 ad * while we copy the data. 164 1.2 ad */ 165 1.2 ad for (i = 0; i < SII_NCMD; i++) { 166 1.2 ad sc->sc_st[i].dmaAddr[0] = (u_short *) 167 1.2 ad sc->sc_buf + 2 * SII_MAX_DMA_XFER_LENGTH * i; 168 1.2 ad sc->sc_st[i].dmaAddr[1] = sc->sc_st[i].dmaAddr[0] + 169 1.2 ad SII_MAX_DMA_XFER_LENGTH; 170 1.2 ad } 171 1.2 ad 172 1.2 ad sii_Reset(sc, RESET); 173 1.2 ad printf(": target %d\n", sc->sc_regs->id & SII_IDMSK); 174 1.2 ad 175 1.9 tsutsui sc->sc_adapter.adapt_dev = sc->sc_dev; 176 1.2 ad sc->sc_adapter.adapt_nchannels = 1; 177 1.2 ad sc->sc_adapter.adapt_openings = 7; 178 1.2 ad sc->sc_adapter.adapt_max_periph = 1; 179 1.2 ad sc->sc_adapter.adapt_ioctl = NULL; 180 1.2 ad sc->sc_adapter.adapt_minphys = minphys; 181 1.2 ad sc->sc_adapter.adapt_request = sii_scsi_request; 182 1.2 ad 183 1.2 ad sc->sc_channel.chan_adapter = &sc->sc_adapter; 184 1.2 ad sc->sc_channel.chan_bustype = &scsi_bustype; 185 1.2 ad sc->sc_channel.chan_channel = 0; 186 1.2 ad sc->sc_channel.chan_ntargets = 8; 187 1.2 ad sc->sc_channel.chan_nluns = 8; 188 1.2 ad sc->sc_channel.chan_id = sc->sc_regs->id & SII_IDMSK; 189 1.2 ad 190 1.2 ad 191 1.2 ad /* 192 1.2 ad * Now try to attach all the sub-devices 193 1.2 ad */ 194 1.16 thorpej config_found(sc->sc_dev, &sc->sc_channel, scsiprint, CFARGS_NONE); 195 1.2 ad } 196 1.2 ad 197 1.2 ad /* 198 1.2 ad * Start activity on a SCSI device. 199 1.2 ad * We maintain information on each device separately since devices can 200 1.2 ad * connect/disconnect during an operation. 201 1.2 ad */ 202 1.2 ad 203 1.2 ad void 204 1.6 dsl sii_scsi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, void *arg) 205 1.2 ad { 206 1.2 ad struct scsipi_xfer *xs; 207 1.2 ad struct scsipi_periph *periph; 208 1.9 tsutsui struct siisoftc *sc; 209 1.2 ad int target; 210 1.2 ad int s; 211 1.2 ad int count; 212 1.2 ad 213 1.9 tsutsui sc = device_private(chan->chan_adapter->adapt_dev); 214 1.9 tsutsui 215 1.2 ad switch (req) { 216 1.2 ad case ADAPTER_REQ_RUN_XFER: 217 1.2 ad xs = arg; 218 1.2 ad periph = xs->xs_periph; 219 1.2 ad target = periph->periph_target; 220 1.2 ad s = splbio(); 221 1.2 ad if (sc->sc_cmd[target]) { 222 1.2 ad splx(s); 223 1.2 ad xs->error = XS_RESOURCE_SHORTAGE; 224 1.2 ad scsipi_done(xs); 225 1.2 ad printf("[busy at start]\n"); 226 1.2 ad return; 227 1.2 ad } 228 1.2 ad /* 229 1.2 ad * Build a ScsiCmd for this command and start it. 230 1.2 ad */ 231 1.2 ad sc->sc_xs[target] = xs; 232 1.2 ad sc->sc_cmd[target] = &sc->sc_cmd_fake[target]; /* XXX */ 233 1.2 ad sc->sc_cmd[target]->unit = 0; 234 1.2 ad sc->sc_cmd[target]->flags = 0; 235 1.2 ad sc->sc_cmd[target]->buflen = xs->datalen; 236 1.2 ad sc->sc_cmd[target]->buf = xs->data; 237 1.2 ad sc->sc_cmd[target]->cmdlen = xs->cmdlen; 238 1.2 ad sc->sc_cmd[target]->cmd = (u_char *)xs->cmd; 239 1.2 ad sc->sc_cmd[target]->lun = xs->xs_periph->periph_lun; 240 1.2 ad sii_StartCmd(sc, target); 241 1.2 ad splx(s); 242 1.2 ad if ((xs->xs_control & XS_CTL_POLL) == 0) 243 1.2 ad return; 244 1.2 ad count = xs->timeout; 245 1.2 ad while (count) { 246 1.2 ad if ((xs->xs_status & XS_STS_DONE) != 0) 247 1.2 ad return; 248 1.2 ad siiintr(sc); 249 1.2 ad /* XXX schedule another command? */ 250 1.2 ad DELAY(1000); 251 1.2 ad --count; 252 1.2 ad } 253 1.2 ad xs->error = XS_TIMEOUT; 254 1.2 ad scsipi_done(xs); 255 1.2 ad return; 256 1.2 ad case ADAPTER_REQ_GROW_RESOURCES: 257 1.2 ad /* XXX Not supported. */ 258 1.2 ad return; 259 1.2 ad 260 1.2 ad case ADAPTER_REQ_SET_XFER_MODE: 261 1.2 ad /* XXX Not supported. */ 262 1.2 ad return; 263 1.2 ad } 264 1.2 ad } 265 1.2 ad 266 1.2 ad /* 267 1.2 ad * Check to see if any SII chips have pending interrupts 268 1.2 ad * and process as appropriate. 269 1.2 ad */ 270 1.2 ad int 271 1.6 dsl siiintr(void *xxxsc) 272 1.2 ad { 273 1.2 ad struct siisoftc *sc = xxxsc; 274 1.2 ad u_int dstat; 275 1.2 ad 276 1.2 ad /* 277 1.2 ad * Find which controller caused the interrupt. 278 1.2 ad */ 279 1.2 ad dstat = sc->sc_regs->dstat; 280 1.2 ad if (dstat & (SII_CI | SII_DI)) { 281 1.2 ad sii_DoIntr(sc, dstat); 282 1.2 ad return (0); /* XXX */ 283 1.2 ad } 284 1.2 ad 285 1.2 ad return (1); /* XXX spurious interrupt? */ 286 1.2 ad } 287 1.2 ad 288 1.2 ad /* 289 1.2 ad * Reset the SII chip and do a SCSI reset if 'reset' is true. 290 1.2 ad * NOTE: if !cold && reset, should probably probe for devices 291 1.2 ad * since a SCSI bus reset will set UNIT_ATTENTION. 292 1.2 ad */ 293 1.2 ad static void 294 1.7 dsl sii_Reset(struct siisoftc* sc, int reset) 295 1.7 dsl /* reset: TRUE => reset SCSI bus */ 296 1.2 ad { 297 1.2 ad SIIRegs *regs = sc->sc_regs; 298 1.2 ad 299 1.2 ad #ifdef DEBUG 300 1.2 ad if (sii_debug > 1) 301 1.2 ad printf("sii: RESET\n"); 302 1.2 ad #endif 303 1.2 ad /* 304 1.2 ad * Reset the SII chip. 305 1.2 ad */ 306 1.2 ad regs->comm = SII_CHRESET; 307 1.2 ad /* 308 1.2 ad * Set arbitrated bus mode. 309 1.2 ad */ 310 1.2 ad regs->csr = SII_HPM; 311 1.2 ad /* 312 1.2 ad * Set host adapter ID (from PROM sciiidN variable). 313 1.2 ad */ 314 1.2 ad /* XXX device_unit() abuse */ 315 1.9 tsutsui regs->id = SII_ID_IO | prom_scsiid(device_unit(sc->sc_dev)); 316 1.2 ad /* 317 1.2 ad * Enable SII to drive the SCSI bus. 318 1.2 ad */ 319 1.2 ad regs->dictrl = SII_PRE; 320 1.2 ad regs->dmctrl = 0; 321 1.2 ad 322 1.2 ad if (reset) { 323 1.2 ad int i; 324 1.2 ad 325 1.2 ad /* 326 1.2 ad * Assert SCSI bus reset for at least 25 Usec to clear the 327 1.2 ad * world. SII_DO_RST is self clearing. 328 1.2 ad * Delay 250 ms before doing any commands. 329 1.2 ad */ 330 1.2 ad regs->comm = SII_DO_RST; 331 1.2 ad wbflush(); 332 1.2 ad DELAY(250000); 333 1.2 ad 334 1.2 ad /* rearbitrate synchronous offset */ 335 1.2 ad for (i = 0; i < SII_NCMD; i++) 336 1.2 ad sc->sc_st[i].dmaReqAck = 0; 337 1.2 ad } 338 1.2 ad 339 1.2 ad /* 340 1.2 ad * Clear any pending interrupts from the reset. 341 1.2 ad */ 342 1.2 ad regs->cstat = regs->cstat; 343 1.2 ad regs->dstat = regs->dstat; 344 1.2 ad /* 345 1.2 ad * Set up SII for arbitrated bus mode, SCSI parity checking, 346 1.2 ad * Reselect Enable, and Interrupt Enable. 347 1.2 ad */ 348 1.2 ad regs->csr = SII_HPM | SII_RSE | SII_PCE | SII_IE; 349 1.2 ad wbflush(); 350 1.2 ad } 351 1.2 ad 352 1.2 ad /* 353 1.2 ad * Start a SCSI command by sending the cmd data 354 1.2 ad * to a SCSI controller via the SII. 355 1.13 maya * Call the device done procedure if it can't be started. 356 1.2 ad * NOTE: we should be called with interrupts disabled. 357 1.2 ad */ 358 1.2 ad static void 359 1.7 dsl sii_StartCmd(struct siisoftc *sc, int target) 360 1.7 dsl /* sc: which SII to use */ 361 1.7 dsl /* target: which command to start */ 362 1.2 ad { 363 1.2 ad SIIRegs *regs; 364 1.2 ad ScsiCmd *scsicmd; 365 1.2 ad State *state; 366 1.2 ad u_int status; 367 1.2 ad int error, retval; 368 1.2 ad 369 1.2 ad /* if another command is currently in progress, just wait */ 370 1.2 ad if (sc->sc_target >= 0) 371 1.2 ad return; 372 1.2 ad 373 1.2 ad /* initialize state information for this command */ 374 1.2 ad scsicmd = sc->sc_cmd[target]; 375 1.2 ad state = &sc->sc_st[target]; 376 1.2 ad state->flags = FIRST_DMA; 377 1.2 ad state->prevComm = 0; 378 1.2 ad state->dmalen = 0; 379 1.2 ad state->dmaCurPhase = -1; 380 1.2 ad state->dmaPrevPhase = -1; 381 1.2 ad state->dmaBufIndex = 0; 382 1.2 ad state->cmd = scsicmd->cmd; 383 1.2 ad state->cmdlen = scsicmd->cmdlen; 384 1.2 ad if ((state->buflen = scsicmd->buflen) == 0) { 385 1.2 ad state->dmaDataPhase = -1; /* illegal phase. shouldn't happen */ 386 1.2 ad state->buf = (char *)0; 387 1.2 ad } else { 388 1.2 ad state->buf = scsicmd->buf; 389 1.2 ad } 390 1.2 ad 391 1.2 ad #ifdef DEBUG 392 1.2 ad if (sii_debug > 1) { 393 1.2 ad printf("sii_StartCmd: %s target %d cmd 0x%x addr %p size %d DMA %d\n", 394 1.9 tsutsui device_xname(sc->sc_dev), 395 1.9 tsutsui target, scsicmd->cmd[0], scsicmd->buf, scsicmd->buflen, 396 1.9 tsutsui state->dmaDataPhase); 397 1.2 ad } 398 1.2 ad sii_debug_cmd = scsicmd->cmd[0]; 399 1.2 ad if (scsicmd->cmd[0] == READ_10 || 400 1.2 ad scsicmd->cmd[0] == WRITE_10) { 401 1.2 ad sii_debug_bn = (scsicmd->cmd[2] << 24) | 402 1.2 ad (scsicmd->cmd[3] << 16) | 403 1.2 ad (scsicmd->cmd[4] << 8) | 404 1.2 ad scsicmd->cmd[5]; 405 1.2 ad sii_debug_sz = (scsicmd->cmd[7] << 8) | scsicmd->cmd[8]; 406 1.2 ad } else { 407 1.2 ad sii_debug_bn = 0; 408 1.2 ad sii_debug_sz = 0; 409 1.2 ad } 410 1.2 ad #endif 411 1.2 ad 412 1.2 ad /* try to select the target */ 413 1.2 ad regs = sc->sc_regs; 414 1.2 ad 415 1.2 ad /* 416 1.2 ad * Another device may have selected us; in which case, 417 1.2 ad * this command will be restarted later. 418 1.2 ad */ 419 1.2 ad if ((status = regs->dstat) & (SII_CI | SII_DI)) { 420 1.2 ad sii_DoIntr(sc, status); 421 1.2 ad return; 422 1.2 ad } 423 1.2 ad 424 1.2 ad sc->sc_target = target; 425 1.2 ad #if 0 426 1.2 ad /* seem to have problems with synchronous transfers */ 427 1.2 ad if (scsicmd->flags & SCSICMD_USE_SYNC) { 428 1.2 ad printf("sii_StartCmd: doing extended msg\n"); /* XXX */ 429 1.2 ad /* 430 1.2 ad * Setup to send both the identify message and the synchronous 431 1.2 ad * data transfer request. 432 1.2 ad */ 433 1.2 ad sii_buf[0] = MSG_IDENTIFYFLAG | MSG_IDENTIFY_DISCFLAG; 434 1.2 ad sii_buf[1] = MSG_EXTENDED; 435 1.2 ad sii_buf[2] = MSG_EXT_SDTR_LEN; 436 1.2 ad sii_buf[3] = MSG_EXT_SDTR; 437 1.2 ad sii_buf[4] = 0; 438 1.2 ad sii_buf[5] = 3; /* maximum SII chip supports */ 439 1.2 ad 440 1.2 ad state->dmaCurPhase = SII_MSG_OUT_PHASE, 441 1.2 ad state->dmalen = 6; 442 1.2 ad sc->sii_copytobuf((u_short *)sii_buf, 443 1.2 ad (volatile u_short *)SII_BUF_ADDR(sc), 6); 444 1.2 ad regs->slcsr = target; 445 1.2 ad regs->dmctrl = state->dmaReqAck; 446 1.2 ad regs->dmaddrl = (u_short)(SII_BUF_ADDR(sc) >> 1); 447 1.2 ad regs->dmaddrh = (u_short)(SII_BUF_ADDR(sc) >> 17) & 03; 448 1.2 ad regs->dmlotc = 6; 449 1.2 ad regs->comm = SII_DMA | SII_INXFER | SII_SELECT | SII_ATN | 450 1.2 ad SII_CON | SII_MSG_OUT_PHASE; 451 1.2 ad } else 452 1.2 ad #endif 453 1.2 ad { 454 1.2 ad /* do a chained, select with ATN and programmed I/O command */ 455 1.2 ad regs->data = MSG_IDENTIFYFLAG | MSG_IDENTIFY_DISCFLAG | 456 1.2 ad scsicmd->lun; 457 1.2 ad regs->slcsr = target; 458 1.2 ad regs->dmctrl = state->dmaReqAck; 459 1.2 ad regs->comm = SII_INXFER | SII_SELECT | SII_ATN | SII_CON | 460 1.2 ad SII_MSG_OUT_PHASE; 461 1.2 ad } 462 1.2 ad wbflush(); 463 1.2 ad 464 1.2 ad /* 465 1.2 ad * Wait for something to happen 466 1.2 ad * (should happen soon or we would use interrupts). 467 1.2 ad */ 468 1.2 ad SII_WAIT_UNTIL(status, regs->cstat, status & (SII_CI | SII_DI), 469 1.2 ad SII_WAIT_COUNT/4, retval); 470 1.2 ad 471 1.2 ad /* check to see if we are connected OK */ 472 1.2 ad if ((status & (SII_RST | SII_SCH | SII_STATE_MSK)) == 473 1.2 ad (SII_SCH | SII_CON)) { 474 1.2 ad regs->cstat = status; 475 1.2 ad wbflush(); 476 1.2 ad 477 1.2 ad #ifdef DEBUG 478 1.2 ad sii_logp->target = target; 479 1.2 ad sii_logp->cstat = status; 480 1.2 ad sii_logp->dstat = 0; 481 1.2 ad sii_logp->comm = regs->comm; 482 1.2 ad sii_logp->msg = -1; 483 1.2 ad sii_logp->rlen = state->buflen; 484 1.2 ad sii_logp->dlen = state->dmalen; 485 1.2 ad if (++sii_logp >= &sii_log[NLOG]) 486 1.2 ad sii_logp = sii_log; 487 1.2 ad #endif 488 1.2 ad 489 1.2 ad /* wait a short time for command phase */ 490 1.2 ad SII_WAIT_UNTIL(status, regs->dstat, status & SII_MIS, 491 1.2 ad SII_WAIT_COUNT, retval); 492 1.2 ad #ifdef DEBUG 493 1.2 ad if (sii_debug > 2) 494 1.2 ad printf("sii_StartCmd: ds %x cnt %d\n", status, retval); 495 1.2 ad #endif 496 1.2 ad if ((status & (SII_CI | SII_MIS | SII_PHASE_MSK)) != 497 1.2 ad (SII_MIS | SII_CMD_PHASE)) { 498 1.2 ad printf("sii_StartCmd: timeout cs %x ds %x cnt %d\n", 499 1.2 ad regs->cstat, status, retval); /* XXX */ 500 1.2 ad /* process interrupt or continue until it happens */ 501 1.2 ad if (status & (SII_CI | SII_DI)) 502 1.2 ad sii_DoIntr(sc, status); 503 1.2 ad return; 504 1.2 ad } 505 1.2 ad regs->dstat = SII_DNE; /* clear Msg Out DMA done */ 506 1.2 ad 507 1.2 ad /* send command data */ 508 1.2 ad sc->sii_copytobuf((u_short *)state->cmd, 509 1.2 ad (volatile u_short *)state->dmaAddr[0], state->cmdlen); 510 1.2 ad sii_StartDMA(regs, state->dmaCurPhase = SII_CMD_PHASE, 511 1.2 ad state->dmaAddr[0], state->dmalen = scsicmd->cmdlen); 512 1.2 ad 513 1.2 ad /* wait a little while for DMA to finish */ 514 1.2 ad SII_WAIT_UNTIL(status, regs->dstat, status & (SII_CI | SII_DI), 515 1.2 ad SII_WAIT_COUNT, retval); 516 1.2 ad #ifdef DEBUG 517 1.2 ad if (sii_debug > 2) 518 1.2 ad printf("sii_StartCmd: ds %x, cnt %d\n", status, retval); 519 1.2 ad #endif 520 1.2 ad if (status & (SII_CI | SII_DI)) 521 1.2 ad sii_DoIntr(sc, status); 522 1.2 ad #ifdef DEBUG 523 1.2 ad if (sii_debug > 2) 524 1.2 ad printf("sii_StartCmd: DONE ds %x\n", regs->dstat); 525 1.2 ad #endif 526 1.2 ad return; 527 1.2 ad } 528 1.2 ad 529 1.2 ad /* 530 1.2 ad * Another device may have selected us; in which case, 531 1.2 ad * this command will be restarted later. 532 1.2 ad */ 533 1.2 ad if (status & (SII_CI | SII_DI)) { 534 1.2 ad sii_DoIntr(sc, regs->dstat); 535 1.2 ad return; 536 1.2 ad } 537 1.2 ad 538 1.2 ad /* 539 1.2 ad * Disconnect if selection command still in progress. 540 1.2 ad */ 541 1.2 ad if (status & SII_SIP) { 542 1.2 ad error = ENXIO; /* device didn't respond */ 543 1.2 ad regs->comm = SII_DISCON; 544 1.2 ad wbflush(); 545 1.2 ad SII_WAIT_UNTIL(status, regs->cstat, 546 1.2 ad !(status & (SII_CON | SII_SIP)), 547 1.2 ad SII_WAIT_COUNT, retval); 548 1.2 ad } else 549 1.2 ad error = EBUSY; /* couldn't get the bus */ 550 1.2 ad #ifdef DEBUG 551 1.2 ad if (sii_debug > 1) 552 1.2 ad printf("sii_StartCmd: Couldn't select target %d error %d\n", 553 1.2 ad target, error); 554 1.2 ad #endif 555 1.2 ad sc->sc_target = -1; 556 1.2 ad regs->cstat = 0xffff; 557 1.2 ad regs->dstat = 0xffff; 558 1.2 ad regs->comm = 0; 559 1.2 ad wbflush(); 560 1.2 ad sii_CmdDone(sc, target, error); 561 1.2 ad } 562 1.2 ad 563 1.2 ad /* 564 1.2 ad * Process interrupt conditions. 565 1.2 ad */ 566 1.2 ad static void 567 1.6 dsl sii_DoIntr(struct siisoftc *sc, u_int dstat) 568 1.2 ad { 569 1.2 ad SIIRegs *regs = sc->sc_regs; 570 1.2 ad State *state; 571 1.2 ad u_int cstat; 572 1.2 ad int i, msg; 573 1.2 ad u_int comm; 574 1.2 ad 575 1.2 ad again: 576 1.2 ad comm = regs->comm; 577 1.2 ad 578 1.2 ad #ifdef DEBUG 579 1.2 ad if (sii_debug > 3) 580 1.2 ad printf("sii_DoIntr: cs %x, ds %x cm %x ", 581 1.2 ad regs->cstat, dstat, comm); 582 1.2 ad sii_logp->target = sc->sc_target; 583 1.2 ad sii_logp->cstat = regs->cstat; 584 1.2 ad sii_logp->dstat = dstat; 585 1.2 ad sii_logp->comm = comm; 586 1.2 ad sii_logp->msg = -1; 587 1.2 ad if (sc->sc_target >= 0) { 588 1.2 ad sii_logp->rlen = sc->sc_st[sc->sc_target].buflen; 589 1.2 ad sii_logp->dlen = sc->sc_st[sc->sc_target].dmalen; 590 1.2 ad } else { 591 1.2 ad sii_logp->rlen = 0; 592 1.2 ad sii_logp->dlen = 0; 593 1.2 ad } 594 1.2 ad if (++sii_logp >= &sii_log[NLOG]) 595 1.2 ad sii_logp = sii_log; 596 1.2 ad #endif 597 1.2 ad 598 1.2 ad regs->dstat = dstat; /* acknowledge everything */ 599 1.2 ad wbflush(); 600 1.2 ad 601 1.2 ad if (dstat & SII_CI) { 602 1.2 ad /* deglitch cstat register */ 603 1.2 ad msg = regs->cstat; 604 1.2 ad while (msg != (cstat = regs->cstat)) 605 1.2 ad msg = cstat; 606 1.2 ad regs->cstat = cstat; /* acknowledge everything */ 607 1.2 ad wbflush(); 608 1.2 ad #ifdef DEBUG 609 1.2 ad if (sii_logp > sii_log) 610 1.2 ad sii_logp[-1].cstat = cstat; 611 1.2 ad else 612 1.2 ad sii_log[NLOG - 1].cstat = cstat; 613 1.2 ad #endif 614 1.2 ad 615 1.2 ad /* check for a BUS RESET */ 616 1.2 ad if (cstat & SII_RST) { 617 1.9 tsutsui printf("%s: SCSI bus reset!!\n", 618 1.9 tsutsui device_xname(sc->sc_dev)); 619 1.2 ad /* need to flush disconnected commands */ 620 1.2 ad for (i = 0; i < SII_NCMD; i++) { 621 1.2 ad if (!sc->sc_cmd[i]) 622 1.2 ad continue; 623 1.2 ad sii_CmdDone(sc, i, EIO); 624 1.2 ad } 625 1.2 ad /* rearbitrate synchronous offset */ 626 1.2 ad for (i = 0; i < SII_NCMD; i++) 627 1.2 ad sc->sc_st[i].dmaReqAck = 0; 628 1.2 ad sc->sc_target = -1; 629 1.2 ad return; 630 1.2 ad } 631 1.2 ad 632 1.2 ad #ifdef notdef 633 1.2 ad /* 634 1.2 ad * Check for a BUS ERROR. 635 1.2 ad * According to DEC, this feature doesn't really work 636 1.2 ad * and to just clear the bit if it's set. 637 1.2 ad */ 638 1.2 ad if (cstat & SII_BER) { 639 1.2 ad regs->cstat = SII_BER; 640 1.2 ad wbflush(); 641 1.2 ad } 642 1.2 ad #endif 643 1.2 ad 644 1.2 ad /* check for state change */ 645 1.2 ad if (cstat & SII_SCH) { 646 1.2 ad sii_StateChg(sc, cstat); 647 1.2 ad comm = regs->comm; 648 1.2 ad } 649 1.2 ad } 650 1.2 ad 651 1.2 ad /* check for DMA completion */ 652 1.2 ad if (dstat & SII_DNE) { 653 1.2 ad u_short *dma; 654 1.2 ad char *buf; 655 1.2 ad 656 1.2 ad /* 657 1.2 ad * There is a race condition with SII_SCH. There is a short 658 1.2 ad * window between the time a SII_SCH is seen after a disconnect 659 1.2 ad * and when the SII_SCH is cleared. A reselect can happen 660 1.2 ad * in this window and we will clear the SII_SCH without 661 1.2 ad * processing the reconnect. 662 1.2 ad */ 663 1.2 ad if (sc->sc_target < 0) { 664 1.2 ad cstat = regs->cstat; 665 1.2 ad printf("%s: target %d DNE?? dev %d,%d cs %x\n", 666 1.9 tsutsui device_xname(sc->sc_dev), sc->sc_target, 667 1.9 tsutsui regs->slcsr, regs->destat, 668 1.9 tsutsui cstat); /* XXX */ 669 1.2 ad if (cstat & SII_DST) { 670 1.2 ad sc->sc_target = regs->destat; 671 1.2 ad state = &sc->sc_st[sc->sc_target]; 672 1.2 ad state->prevComm = 0; 673 1.2 ad } else 674 1.2 ad panic("sc_target 1"); 675 1.2 ad } 676 1.2 ad state = &sc->sc_st[sc->sc_target]; 677 1.2 ad /* check for a PARITY ERROR */ 678 1.2 ad if (dstat & SII_IPE) { 679 1.2 ad state->flags |= PARITY_ERR; 680 1.9 tsutsui printf("%s: Parity error!!\n", 681 1.9 tsutsui device_xname(sc->sc_dev)); 682 1.2 ad goto abort; 683 1.2 ad } 684 1.15 andvar /* dmalen = amount left to transfer, i = amount transferred */ 685 1.2 ad i = state->dmalen; 686 1.2 ad state->dmalen = 0; 687 1.2 ad state->dmaCurPhase = -1; 688 1.2 ad #ifdef DEBUG 689 1.2 ad if (sii_debug > 4) { 690 1.2 ad printf("DNE: amt %d ", i); 691 1.2 ad if (!(dstat & SII_TCZ)) 692 1.2 ad printf("no TCZ?? (%d) ", regs->dmlotc); 693 1.2 ad } else if (!(dstat & SII_TCZ)) { 694 1.2 ad printf("%s: device %d: no TCZ?? (%d)\n", 695 1.9 tsutsui device_xname(sc->sc_dev), 696 1.9 tsutsui sc->sc_target, regs->dmlotc); 697 1.2 ad sii_DumpLog(); /* XXX */ 698 1.2 ad } 699 1.2 ad #endif 700 1.2 ad switch (comm & SII_PHASE_MSK) { 701 1.2 ad case SII_CMD_PHASE: 702 1.2 ad state->cmdlen -= i; 703 1.2 ad break; 704 1.2 ad 705 1.2 ad case SII_DATA_IN_PHASE: 706 1.2 ad /* check for more data for the same phase */ 707 1.2 ad dma = state->dmaAddr[state->dmaBufIndex]; 708 1.2 ad buf = state->buf; 709 1.2 ad state->buf += i; 710 1.2 ad state->buflen -= i; 711 1.2 ad if (state->buflen > 0 && !(dstat & SII_MIS)) { 712 1.2 ad int len; 713 1.2 ad 714 1.2 ad /* start reading next chunk */ 715 1.2 ad len = state->buflen; 716 1.2 ad if (len > SII_MAX_DMA_XFER_LENGTH) 717 1.2 ad len = SII_MAX_DMA_XFER_LENGTH; 718 1.2 ad state->dmaBufIndex = !state->dmaBufIndex; 719 1.2 ad sii_StartDMA(regs, 720 1.2 ad state->dmaCurPhase = SII_DATA_IN_PHASE, 721 1.2 ad state->dmaAddr[state->dmaBufIndex], 722 1.2 ad state->dmaCnt = state->dmalen = len); 723 1.2 ad dstat &= ~(SII_IBF | SII_TBE); 724 1.2 ad } 725 1.2 ad /* copy in the data */ 726 1.2 ad sc->sii_copyfrombuf((volatile u_short *)dma, buf, i); 727 1.2 ad break; 728 1.2 ad 729 1.2 ad case SII_DATA_OUT_PHASE: 730 1.2 ad state->dmaBufIndex = !state->dmaBufIndex; 731 1.2 ad state->buf += i; 732 1.2 ad state->buflen -= i; 733 1.2 ad 734 1.2 ad /* check for more data for the same phase */ 735 1.2 ad if (state->buflen <= 0 || (dstat & SII_MIS)) 736 1.2 ad break; 737 1.2 ad 738 1.2 ad /* start next chunk */ 739 1.2 ad i = state->buflen; 740 1.2 ad if (i > SII_MAX_DMA_XFER_LENGTH) { 741 1.2 ad sii_StartDMA(regs, state->dmaCurPhase = 742 1.2 ad SII_DATA_OUT_PHASE, 743 1.2 ad state->dmaAddr[state->dmaBufIndex], 744 1.2 ad state->dmaCnt = state->dmalen = 745 1.2 ad SII_MAX_DMA_XFER_LENGTH); 746 1.2 ad /* prepare for next chunk */ 747 1.2 ad i -= SII_MAX_DMA_XFER_LENGTH; 748 1.2 ad if (i > SII_MAX_DMA_XFER_LENGTH) 749 1.2 ad i = SII_MAX_DMA_XFER_LENGTH; 750 1.2 ad sc->sii_copytobuf((u_short *)(state->buf + 751 1.2 ad SII_MAX_DMA_XFER_LENGTH), 752 1.2 ad (volatile u_short *) 753 1.2 ad state->dmaAddr[!state->dmaBufIndex], i); 754 1.2 ad } else { 755 1.2 ad sii_StartDMA(regs, state->dmaCurPhase = 756 1.2 ad SII_DATA_OUT_PHASE, 757 1.2 ad state->dmaAddr[state->dmaBufIndex], 758 1.2 ad state->dmaCnt = state->dmalen = i); 759 1.2 ad } 760 1.2 ad dstat &= ~(SII_IBF | SII_TBE); 761 1.2 ad } 762 1.2 ad } 763 1.2 ad 764 1.2 ad /* check for phase change or another MsgIn/Out */ 765 1.2 ad if (dstat & (SII_MIS | SII_IBF | SII_TBE)) { 766 1.2 ad /* 767 1.2 ad * There is a race condition with SII_SCH. There is a short 768 1.2 ad * window between the time a SII_SCH is seen after a disconnect 769 1.2 ad * and when the SII_SCH is cleared. A reselect can happen 770 1.2 ad * in this window and we will clear the SII_SCH without 771 1.2 ad * processing the reconnect. 772 1.2 ad */ 773 1.2 ad if (sc->sc_target < 0) { 774 1.2 ad cstat = regs->cstat; 775 1.2 ad printf("%s: target %d MIS?? dev %d,%d cs %x ds %x\n", 776 1.9 tsutsui device_xname(sc->sc_dev), sc->sc_target, 777 1.9 tsutsui regs->slcsr, regs->destat, 778 1.9 tsutsui cstat, dstat); /* XXX */ 779 1.2 ad if (cstat & SII_DST) { 780 1.2 ad sc->sc_target = regs->destat; 781 1.2 ad state = &sc->sc_st[sc->sc_target]; 782 1.2 ad state->prevComm = 0; 783 1.2 ad } else { 784 1.2 ad #ifdef DEBUG 785 1.2 ad sii_DumpLog(); 786 1.2 ad #endif 787 1.2 ad panic("sc_target 2"); 788 1.2 ad } 789 1.2 ad } 790 1.2 ad state = &sc->sc_st[sc->sc_target]; 791 1.2 ad switch (dstat & SII_PHASE_MSK) { 792 1.2 ad case SII_CMD_PHASE: 793 1.2 ad if (state->dmaPrevPhase >= 0) { 794 1.2 ad /* restart DMA after disconnect/reconnect */ 795 1.2 ad if (state->dmaPrevPhase != SII_CMD_PHASE) { 796 1.2 ad printf("%s: device %d: DMA reselect phase doesn't match\n", 797 1.9 tsutsui device_xname(sc->sc_dev), 798 1.9 tsutsui sc->sc_target); 799 1.2 ad goto abort; 800 1.2 ad } 801 1.2 ad state->dmaCurPhase = SII_CMD_PHASE; 802 1.2 ad state->dmaPrevPhase = -1; 803 1.2 ad regs->dmaddrl = state->dmaAddrL; 804 1.2 ad regs->dmaddrh = state->dmaAddrH; 805 1.2 ad regs->dmlotc = state->dmaCnt; 806 1.2 ad if (state->dmaCnt & 1) 807 1.2 ad regs->dmabyte = state->dmaByte; 808 1.2 ad regs->comm = SII_DMA | SII_INXFER | 809 1.2 ad (comm & SII_STATE_MSK) | SII_CMD_PHASE; 810 1.2 ad wbflush(); 811 1.2 ad #ifdef DEBUG 812 1.2 ad if (sii_debug > 4) 813 1.2 ad printf("Cmd dcnt %d dadr %x ", 814 1.2 ad state->dmaCnt, 815 1.2 ad (state->dmaAddrH << 16) | 816 1.2 ad state->dmaAddrL); 817 1.2 ad #endif 818 1.2 ad } else { 819 1.2 ad /* send command data */ 820 1.2 ad i = state->cmdlen; 821 1.2 ad if (i == 0) { 822 1.2 ad printf("%s: device %d: cmd count exceeded\n", 823 1.9 tsutsui device_xname(sc->sc_dev), 824 1.9 tsutsui sc->sc_target); 825 1.2 ad goto abort; 826 1.2 ad } 827 1.2 ad sc->sii_copytobuf((u_short *)state->cmd, 828 1.2 ad (volatile u_short *)state->dmaAddr[0], 829 1.2 ad i); 830 1.2 ad sii_StartDMA(regs, state->dmaCurPhase = 831 1.2 ad SII_CMD_PHASE, state->dmaAddr[0], 832 1.2 ad state->dmaCnt = state->dmalen = i); 833 1.2 ad } 834 1.2 ad /* wait a short time for XFER complete */ 835 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, 836 1.2 ad dstat & (SII_CI | SII_DI), SII_WAIT_COUNT, i); 837 1.2 ad if (dstat & (SII_CI | SII_DI)) { 838 1.2 ad #ifdef DEBUG 839 1.2 ad if (sii_debug > 4) 840 1.2 ad printf("cnt %d\n", i); 841 1.2 ad else if (sii_debug > 0) 842 1.2 ad printf("sii_DoIntr: cmd wait ds %x cnt %d\n", 843 1.2 ad dstat, i); 844 1.2 ad #endif 845 1.2 ad goto again; 846 1.2 ad } 847 1.2 ad break; 848 1.2 ad 849 1.2 ad case SII_DATA_IN_PHASE: 850 1.2 ad case SII_DATA_OUT_PHASE: 851 1.2 ad if (state->cmdlen > 0) { 852 1.2 ad printf("%s: device %d: cmd %x: command data not all sent (%d) 1\n", 853 1.9 tsutsui device_xname(sc->sc_dev), sc->sc_target, 854 1.9 tsutsui sc->sc_cmd[sc->sc_target]->cmd[0], 855 1.9 tsutsui state->cmdlen); 856 1.2 ad state->cmdlen = 0; 857 1.2 ad #ifdef DEBUG 858 1.2 ad sii_DumpLog(); 859 1.2 ad #endif 860 1.2 ad } 861 1.2 ad if (state->dmaPrevPhase >= 0) { 862 1.2 ad /* restart DMA after disconnect/reconnect */ 863 1.2 ad if (state->dmaPrevPhase != 864 1.2 ad (dstat & SII_PHASE_MSK)) { 865 1.2 ad printf("%s: device %d: DMA reselect phase doesn't match\n", 866 1.9 tsutsui device_xname(sc->sc_dev), 867 1.9 tsutsui sc->sc_target); 868 1.2 ad goto abort; 869 1.2 ad } 870 1.2 ad state->dmaCurPhase = state->dmaPrevPhase; 871 1.2 ad state->dmaPrevPhase = -1; 872 1.2 ad regs->dmaddrl = state->dmaAddrL; 873 1.2 ad regs->dmaddrh = state->dmaAddrH; 874 1.2 ad regs->dmlotc = state->dmaCnt; 875 1.2 ad if (state->dmaCnt & 1) 876 1.2 ad regs->dmabyte = state->dmaByte; 877 1.2 ad regs->comm = SII_DMA | SII_INXFER | 878 1.2 ad (comm & SII_STATE_MSK) | 879 1.2 ad state->dmaCurPhase; 880 1.2 ad wbflush(); 881 1.2 ad #ifdef DEBUG 882 1.2 ad if (sii_debug > 4) 883 1.2 ad printf("Data %d dcnt %d dadr %x ", 884 1.2 ad state->dmaDataPhase, 885 1.2 ad state->dmaCnt, 886 1.2 ad (state->dmaAddrH << 16) | 887 1.2 ad state->dmaAddrL); 888 1.2 ad #endif 889 1.2 ad break; 890 1.2 ad } 891 1.2 ad #ifdef DEBUG 892 1.2 ad if (sii_debug > 4) { 893 1.2 ad printf("Data %d ", state->dmaDataPhase); 894 1.2 ad if (sii_debug > 5) 895 1.2 ad printf("\n"); 896 1.2 ad } 897 1.2 ad #endif 898 1.2 ad i = state->buflen; 899 1.2 ad if (i == 0) { 900 1.2 ad printf("%s: device %d: data count exceeded\n", 901 1.9 tsutsui device_xname(sc->sc_dev), sc->sc_target); 902 1.2 ad goto abort; 903 1.2 ad } 904 1.2 ad if (i > SII_MAX_DMA_XFER_LENGTH) 905 1.2 ad i = SII_MAX_DMA_XFER_LENGTH; 906 1.2 ad if ((dstat & SII_PHASE_MSK) == SII_DATA_IN_PHASE) { 907 1.2 ad sii_StartDMA(regs, 908 1.2 ad state->dmaCurPhase = SII_DATA_IN_PHASE, 909 1.2 ad state->dmaAddr[state->dmaBufIndex], 910 1.2 ad state->dmaCnt = state->dmalen = i); 911 1.2 ad break; 912 1.2 ad } 913 1.2 ad /* start first chunk */ 914 1.2 ad if (state->flags & FIRST_DMA) { 915 1.2 ad state->flags &= ~FIRST_DMA; 916 1.2 ad sc->sii_copytobuf((u_short *)state->buf, 917 1.2 ad (volatile u_short *) 918 1.2 ad state->dmaAddr[state->dmaBufIndex], i); 919 1.2 ad } 920 1.2 ad sii_StartDMA(regs, 921 1.2 ad state->dmaCurPhase = SII_DATA_OUT_PHASE, 922 1.2 ad state->dmaAddr[state->dmaBufIndex], 923 1.2 ad state->dmaCnt = state->dmalen = i); 924 1.2 ad i = state->buflen - SII_MAX_DMA_XFER_LENGTH; 925 1.2 ad if (i > 0) { 926 1.2 ad /* prepare for next chunk */ 927 1.2 ad if (i > SII_MAX_DMA_XFER_LENGTH) 928 1.2 ad i = SII_MAX_DMA_XFER_LENGTH; 929 1.2 ad sc->sii_copytobuf((u_short *)(state->buf + 930 1.2 ad SII_MAX_DMA_XFER_LENGTH), 931 1.2 ad (volatile u_short *) 932 1.2 ad state->dmaAddr[!state->dmaBufIndex], i); 933 1.2 ad } 934 1.2 ad break; 935 1.2 ad 936 1.2 ad case SII_STATUS_PHASE: 937 1.2 ad if (state->cmdlen > 0) { 938 1.2 ad printf("%s: device %d: cmd %x: command data not all sent (%d) 2\n", 939 1.9 tsutsui device_xname(sc->sc_dev), sc->sc_target, 940 1.9 tsutsui sc->sc_cmd[sc->sc_target]->cmd[0], 941 1.9 tsutsui state->cmdlen); 942 1.2 ad state->cmdlen = 0; 943 1.2 ad #ifdef DEBUG 944 1.2 ad sii_DumpLog(); 945 1.2 ad #endif 946 1.2 ad } 947 1.2 ad 948 1.15 andvar /* read amount transferred if DMA didn't finish */ 949 1.2 ad if (state->dmalen > 0) { 950 1.2 ad i = state->dmalen - regs->dmlotc; 951 1.2 ad state->dmalen = 0; 952 1.2 ad state->dmaCurPhase = -1; 953 1.2 ad regs->dmlotc = 0; 954 1.2 ad regs->comm = comm & 955 1.2 ad (SII_STATE_MSK | SII_PHASE_MSK); 956 1.2 ad wbflush(); 957 1.2 ad regs->dstat = SII_DNE; 958 1.2 ad wbflush(); 959 1.2 ad #ifdef DEBUG 960 1.2 ad if (sii_debug > 4) 961 1.2 ad printf("DMA amt %d ", i); 962 1.2 ad #endif 963 1.2 ad switch (comm & SII_PHASE_MSK) { 964 1.2 ad case SII_DATA_IN_PHASE: 965 1.2 ad /* copy in the data */ 966 1.2 ad sc->sii_copyfrombuf((volatile u_short*) 967 1.2 ad state->dmaAddr[state->dmaBufIndex], 968 1.2 ad state->buf, i); 969 1.2 ad 970 1.2 ad case SII_CMD_PHASE: 971 1.2 ad case SII_DATA_OUT_PHASE: 972 1.2 ad state->buflen -= i; 973 1.2 ad } 974 1.2 ad } 975 1.2 ad 976 1.2 ad /* read a one byte status message */ 977 1.2 ad state->statusByte = msg = 978 1.2 ad sii_GetByte(regs, SII_STATUS_PHASE, 1); 979 1.2 ad if (msg < 0) { 980 1.2 ad dstat = regs->dstat; 981 1.2 ad goto again; 982 1.2 ad } 983 1.2 ad #ifdef DEBUG 984 1.2 ad if (sii_debug > 4) 985 1.2 ad printf("Status %x ", msg); 986 1.2 ad if (sii_logp > sii_log) 987 1.2 ad sii_logp[-1].msg = msg; 988 1.2 ad else 989 1.2 ad sii_log[NLOG - 1].msg = msg; 990 1.2 ad #endif 991 1.2 ad 992 1.2 ad /* do a quick wait for COMMAND_COMPLETE */ 993 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, 994 1.2 ad dstat & (SII_CI | SII_DI), SII_WAIT_COUNT, i); 995 1.2 ad if (dstat & (SII_CI | SII_DI)) { 996 1.2 ad #ifdef DEBUG 997 1.2 ad if (sii_debug > 4) 998 1.2 ad printf("cnt2 %d\n", i); 999 1.2 ad #endif 1000 1.2 ad goto again; 1001 1.2 ad } 1002 1.2 ad break; 1003 1.2 ad 1004 1.2 ad case SII_MSG_IN_PHASE: 1005 1.2 ad /* 1006 1.2 ad * Save DMA state if DMA didn't finish. 1007 1.2 ad * Be careful not to save state again after reconnect 1008 1.2 ad * and see RESTORE_POINTER message. 1009 1.2 ad * Note that the SII DMA address is not incremented 1010 1.2 ad * as DMA proceeds. 1011 1.2 ad */ 1012 1.2 ad if (state->dmaCurPhase >= 0) { 1013 1.2 ad /* save DMA registers */ 1014 1.2 ad state->dmaPrevPhase = state->dmaCurPhase; 1015 1.2 ad state->dmaCurPhase = -1; 1016 1.2 ad if (dstat & SII_OBB) 1017 1.2 ad state->dmaByte = regs->dmabyte; 1018 1.2 ad i = regs->dmlotc; 1019 1.2 ad if (i != 0) 1020 1.2 ad i = state->dmaCnt - i; 1021 1.2 ad /* note: no carry from dmaddrl to dmaddrh */ 1022 1.2 ad state->dmaAddrL = regs->dmaddrl + i; 1023 1.2 ad state->dmaAddrH = regs->dmaddrh; 1024 1.2 ad state->dmaCnt = regs->dmlotc; 1025 1.2 ad if (state->dmaCnt == 0) 1026 1.2 ad state->dmaCnt = SII_MAX_DMA_XFER_LENGTH; 1027 1.2 ad regs->comm = comm & 1028 1.2 ad (SII_STATE_MSK | SII_PHASE_MSK); 1029 1.2 ad wbflush(); 1030 1.2 ad regs->dstat = SII_DNE; 1031 1.2 ad wbflush(); 1032 1.2 ad #ifdef DEBUG 1033 1.2 ad if (sii_debug > 4) { 1034 1.2 ad printf("SavP dcnt %d dadr %x ", 1035 1.2 ad state->dmaCnt, 1036 1.2 ad (state->dmaAddrH << 16) | 1037 1.2 ad state->dmaAddrL); 1038 1.2 ad if (((dstat & SII_OBB) != 0) ^ 1039 1.2 ad (state->dmaCnt & 1)) 1040 1.2 ad printf("OBB??? "); 1041 1.2 ad } else if (sii_debug > 0) { 1042 1.2 ad if (((dstat & SII_OBB) != 0) ^ 1043 1.2 ad (state->dmaCnt & 1)) { 1044 1.2 ad printf("sii_DoIntr: OBB??? ds %x cnt %d\n", 1045 1.2 ad dstat, state->dmaCnt); 1046 1.2 ad sii_DumpLog(); 1047 1.2 ad } 1048 1.2 ad } 1049 1.2 ad #endif 1050 1.2 ad } 1051 1.2 ad 1052 1.2 ad /* read a one byte message */ 1053 1.2 ad msg = sii_GetByte(regs, SII_MSG_IN_PHASE, 0); 1054 1.2 ad if (msg < 0) { 1055 1.2 ad dstat = regs->dstat; 1056 1.2 ad goto again; 1057 1.2 ad } 1058 1.2 ad #ifdef DEBUG 1059 1.2 ad if (sii_debug > 4) 1060 1.2 ad printf("MsgIn %x ", msg); 1061 1.2 ad if (sii_logp > sii_log) 1062 1.2 ad sii_logp[-1].msg = msg; 1063 1.2 ad else 1064 1.2 ad sii_log[NLOG - 1].msg = msg; 1065 1.2 ad #endif 1066 1.2 ad 1067 1.2 ad /* process message */ 1068 1.2 ad switch (msg) { 1069 1.2 ad case MSG_CMDCOMPLETE: 1070 1.2 ad /* acknowledge last byte */ 1071 1.2 ad regs->comm = SII_INXFER | SII_MSG_IN_PHASE | 1072 1.2 ad (comm & SII_STATE_MSK); 1073 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, 1074 1.2 ad dstat & SII_DNE, SII_WAIT_COUNT, i); 1075 1.2 ad regs->dstat = SII_DNE; 1076 1.2 ad wbflush(); 1077 1.2 ad msg = sc->sc_target; 1078 1.2 ad sc->sc_target = -1; 1079 1.2 ad /* 1080 1.2 ad * Wait a short time for disconnect. 1081 1.2 ad * Don't be fooled if SII_BER happens first. 1082 1.2 ad * Note: a reselect may happen here. 1083 1.2 ad */ 1084 1.2 ad SII_WAIT_UNTIL(cstat, regs->cstat, 1085 1.2 ad cstat & (SII_RST | SII_SCH), 1086 1.2 ad SII_WAIT_COUNT, i); 1087 1.2 ad if ((cstat & (SII_RST | SII_SCH | 1088 1.2 ad SII_STATE_MSK)) == SII_SCH) { 1089 1.2 ad regs->cstat = SII_SCH | SII_BER; 1090 1.2 ad regs->comm = 0; 1091 1.2 ad wbflush(); 1092 1.2 ad /* 1093 1.2 ad * Double check that we didn't miss a 1094 1.2 ad * state change between seeing it and 1095 1.2 ad * clearing the SII_SCH bit. 1096 1.2 ad */ 1097 1.2 ad i = regs->cstat; 1098 1.2 ad if (!(i & SII_SCH) && 1099 1.2 ad (i & SII_STATE_MSK) != 1100 1.2 ad (cstat & SII_STATE_MSK)) 1101 1.2 ad sii_StateChg(sc, i); 1102 1.2 ad } 1103 1.2 ad #ifdef DEBUG 1104 1.2 ad if (sii_debug > 4) 1105 1.2 ad printf("cs %x\n", cstat); 1106 1.2 ad #endif 1107 1.2 ad sii_CmdDone(sc, msg, 0); 1108 1.2 ad break; 1109 1.2 ad 1110 1.2 ad case MSG_EXTENDED: 1111 1.2 ad /* acknowledge last byte */ 1112 1.2 ad regs->comm = SII_INXFER | SII_MSG_IN_PHASE | 1113 1.2 ad (comm & SII_STATE_MSK); 1114 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, 1115 1.2 ad dstat & SII_DNE, SII_WAIT_COUNT, i); 1116 1.2 ad regs->dstat = SII_DNE; 1117 1.2 ad wbflush(); 1118 1.2 ad /* read the message length */ 1119 1.2 ad msg = sii_GetByte(regs, SII_MSG_IN_PHASE, 1); 1120 1.2 ad if (msg < 0) { 1121 1.2 ad dstat = regs->dstat; 1122 1.2 ad goto again; 1123 1.2 ad } 1124 1.2 ad sii_buf[1] = msg; /* message length */ 1125 1.2 ad if (msg == 0) 1126 1.2 ad msg = 256; 1127 1.2 ad /* 1128 1.13 maya * We read and acknowledge all the bytes 1129 1.2 ad * except the last so we can assert ATN 1130 1.2 ad * if needed before acknowledging the last. 1131 1.2 ad */ 1132 1.2 ad for (i = 0; i < msg; i++) { 1133 1.2 ad dstat = sii_GetByte(regs, 1134 1.2 ad SII_MSG_IN_PHASE, i < msg - 1); 1135 1.2 ad if ((int)dstat < 0) { 1136 1.2 ad dstat = regs->dstat; 1137 1.2 ad goto again; 1138 1.2 ad } 1139 1.2 ad sii_buf[i + 2] = dstat; 1140 1.2 ad } 1141 1.2 ad 1142 1.2 ad switch (sii_buf[2]) { 1143 1.2 ad case MSG_EXT_MODIFY_DATA_PTR: 1144 1.2 ad /* acknowledge last byte */ 1145 1.2 ad regs->comm = SII_INXFER | 1146 1.2 ad SII_MSG_IN_PHASE | 1147 1.2 ad (comm & SII_STATE_MSK); 1148 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, 1149 1.2 ad dstat & SII_DNE, 1150 1.2 ad SII_WAIT_COUNT, i); 1151 1.2 ad regs->dstat = SII_DNE; 1152 1.2 ad wbflush(); 1153 1.2 ad i = (sii_buf[3] << 24) | 1154 1.2 ad (sii_buf[4] << 16) | 1155 1.2 ad (sii_buf[5] << 8) | 1156 1.2 ad sii_buf[6]; 1157 1.2 ad if (state->dmaPrevPhase >= 0) { 1158 1.2 ad state->dmaAddrL += i; 1159 1.2 ad state->dmaCnt -= i; 1160 1.2 ad } 1161 1.2 ad break; 1162 1.2 ad 1163 1.2 ad case MSG_EXT_SDTR_LEN: 1164 1.2 ad /* 1165 1.2 ad * Acknowledge last byte and 1166 1.2 ad * signal a request for MSG_OUT. 1167 1.2 ad */ 1168 1.2 ad regs->comm = SII_INXFER | SII_ATN | 1169 1.2 ad SII_MSG_IN_PHASE | 1170 1.2 ad (comm & SII_STATE_MSK); 1171 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, 1172 1.2 ad dstat & SII_DNE, 1173 1.2 ad SII_WAIT_COUNT, i); 1174 1.2 ad regs->dstat = SII_DNE; 1175 1.2 ad wbflush(); 1176 1.2 ad sii_DoSync(regs, state); 1177 1.2 ad break; 1178 1.2 ad 1179 1.2 ad default: 1180 1.2 ad reject: 1181 1.2 ad /* 1182 1.2 ad * Acknowledge last byte and 1183 1.2 ad * signal a request for MSG_OUT. 1184 1.2 ad */ 1185 1.2 ad regs->comm = SII_INXFER | SII_ATN | 1186 1.2 ad SII_MSG_IN_PHASE | 1187 1.2 ad (comm & SII_STATE_MSK); 1188 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, 1189 1.2 ad dstat & SII_DNE, 1190 1.2 ad SII_WAIT_COUNT, i); 1191 1.2 ad regs->dstat = SII_DNE; 1192 1.2 ad wbflush(); 1193 1.2 ad 1194 1.2 ad /* wait for MSG_OUT phase */ 1195 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, 1196 1.2 ad dstat & SII_TBE, 1197 1.2 ad SII_WAIT_COUNT, i); 1198 1.2 ad 1199 1.2 ad /* send a reject message */ 1200 1.2 ad regs->data = MSG_MESSAGE_REJECT; 1201 1.2 ad regs->comm = SII_INXFER | 1202 1.2 ad (regs->cstat & SII_STATE_MSK) | 1203 1.2 ad SII_MSG_OUT_PHASE; 1204 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, 1205 1.2 ad dstat & SII_DNE, 1206 1.2 ad SII_WAIT_COUNT, i); 1207 1.2 ad regs->dstat = SII_DNE; 1208 1.2 ad wbflush(); 1209 1.2 ad } 1210 1.2 ad break; 1211 1.2 ad 1212 1.2 ad case MSG_SAVEDATAPOINTER: 1213 1.2 ad case MSG_RESTOREPOINTERS: 1214 1.2 ad /* acknowledge last byte */ 1215 1.2 ad regs->comm = SII_INXFER | SII_MSG_IN_PHASE | 1216 1.2 ad (comm & SII_STATE_MSK); 1217 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, 1218 1.2 ad dstat & SII_DNE, SII_WAIT_COUNT, i); 1219 1.2 ad regs->dstat = SII_DNE; 1220 1.2 ad wbflush(); 1221 1.2 ad /* wait a short time for another msg */ 1222 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, 1223 1.2 ad dstat & (SII_CI | SII_DI), 1224 1.2 ad SII_WAIT_COUNT, i); 1225 1.2 ad if (dstat & (SII_CI | SII_DI)) { 1226 1.2 ad #ifdef DEBUG 1227 1.2 ad if (sii_debug > 4) 1228 1.2 ad printf("cnt %d\n", i); 1229 1.2 ad #endif 1230 1.2 ad goto again; 1231 1.2 ad } 1232 1.2 ad break; 1233 1.2 ad 1234 1.2 ad case MSG_DISCONNECT: 1235 1.2 ad /* acknowledge last byte */ 1236 1.2 ad regs->comm = SII_INXFER | SII_MSG_IN_PHASE | 1237 1.2 ad (comm & SII_STATE_MSK); 1238 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, 1239 1.2 ad dstat & SII_DNE, SII_WAIT_COUNT, i); 1240 1.2 ad regs->dstat = SII_DNE; 1241 1.2 ad wbflush(); 1242 1.2 ad state->prevComm = comm; 1243 1.2 ad #ifdef DEBUG 1244 1.2 ad if (sii_debug > 4) 1245 1.2 ad printf("disconn %d ", sc->sc_target); 1246 1.2 ad #endif 1247 1.2 ad /* 1248 1.2 ad * Wait a short time for disconnect. 1249 1.2 ad * Don't be fooled if SII_BER happens first. 1250 1.2 ad * Note: a reselect may happen here. 1251 1.2 ad */ 1252 1.2 ad SII_WAIT_UNTIL(cstat, regs->cstat, 1253 1.2 ad cstat & (SII_RST | SII_SCH), 1254 1.2 ad SII_WAIT_COUNT, i); 1255 1.2 ad if ((cstat & (SII_RST | SII_SCH | 1256 1.2 ad SII_STATE_MSK)) != SII_SCH) { 1257 1.2 ad #ifdef DEBUG 1258 1.2 ad if (sii_debug > 4) 1259 1.2 ad printf("cnt %d\n", i); 1260 1.2 ad #endif 1261 1.2 ad dstat = regs->dstat; 1262 1.2 ad goto again; 1263 1.2 ad } 1264 1.2 ad regs->cstat = SII_SCH | SII_BER; 1265 1.2 ad regs->comm = 0; 1266 1.2 ad wbflush(); 1267 1.2 ad sc->sc_target = -1; 1268 1.2 ad /* 1269 1.2 ad * Double check that we didn't miss a state 1270 1.2 ad * change between seeing it and clearing 1271 1.2 ad * the SII_SCH bit. 1272 1.2 ad */ 1273 1.2 ad i = regs->cstat; 1274 1.2 ad if (!(i & SII_SCH) && (i & SII_STATE_MSK) != 1275 1.2 ad (cstat & SII_STATE_MSK)) 1276 1.2 ad sii_StateChg(sc, i); 1277 1.2 ad break; 1278 1.2 ad 1279 1.2 ad case MSG_MESSAGE_REJECT: 1280 1.2 ad /* acknowledge last byte */ 1281 1.2 ad regs->comm = SII_INXFER | SII_MSG_IN_PHASE | 1282 1.2 ad (comm & SII_STATE_MSK); 1283 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, 1284 1.2 ad dstat & SII_DNE, SII_WAIT_COUNT, i); 1285 1.2 ad regs->dstat = SII_DNE; 1286 1.2 ad wbflush(); 1287 1.2 ad printf("%s: device %d: message reject.\n", 1288 1.9 tsutsui device_xname(sc->sc_dev), sc->sc_target); 1289 1.2 ad break; 1290 1.2 ad 1291 1.2 ad default: 1292 1.2 ad if (!(msg & MSG_IDENTIFYFLAG)) { 1293 1.2 ad printf("%s: device %d: couldn't handle " 1294 1.2 ad "message 0x%x... rejecting.\n", 1295 1.9 tsutsui device_xname(sc->sc_dev), 1296 1.9 tsutsui sc->sc_target, 1297 1.2 ad msg); 1298 1.2 ad #ifdef DEBUG 1299 1.2 ad sii_DumpLog(); 1300 1.2 ad #endif 1301 1.2 ad goto reject; 1302 1.2 ad } 1303 1.2 ad /* acknowledge last byte */ 1304 1.2 ad regs->comm = SII_INXFER | SII_MSG_IN_PHASE | 1305 1.2 ad (comm & SII_STATE_MSK); 1306 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, 1307 1.2 ad dstat & SII_DNE, SII_WAIT_COUNT, i); 1308 1.2 ad regs->dstat = SII_DNE; 1309 1.2 ad wbflush(); 1310 1.2 ad /* may want to check LUN some day */ 1311 1.2 ad /* wait a short time for another msg */ 1312 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, 1313 1.2 ad dstat & (SII_CI | SII_DI), 1314 1.2 ad SII_WAIT_COUNT, i); 1315 1.2 ad if (dstat & (SII_CI | SII_DI)) { 1316 1.2 ad #ifdef DEBUG 1317 1.2 ad if (sii_debug > 4) 1318 1.2 ad printf("cnt %d\n", i); 1319 1.2 ad #endif 1320 1.2 ad goto again; 1321 1.2 ad } 1322 1.2 ad } 1323 1.2 ad break; 1324 1.2 ad 1325 1.2 ad case SII_MSG_OUT_PHASE: 1326 1.2 ad #ifdef DEBUG 1327 1.2 ad if (sii_debug > 4) 1328 1.2 ad printf("MsgOut\n"); 1329 1.2 ad #endif 1330 1.2 ad printf("MsgOut %x\n", state->flags); /* XXX */ 1331 1.2 ad 1332 1.2 ad /* 1333 1.2 ad * Check for parity error. 1334 1.2 ad * Hardware will automatically set ATN 1335 1.2 ad * to request the device for a MSG_OUT phase. 1336 1.2 ad */ 1337 1.2 ad if (state->flags & PARITY_ERR) { 1338 1.2 ad state->flags &= ~PARITY_ERR; 1339 1.2 ad regs->data = MSG_PARITY_ERROR; 1340 1.2 ad } else 1341 1.2 ad regs->data = MSG_NOOP; 1342 1.2 ad regs->comm = SII_INXFER | (comm & SII_STATE_MSK) | 1343 1.2 ad SII_MSG_OUT_PHASE; 1344 1.2 ad wbflush(); 1345 1.2 ad 1346 1.2 ad /* wait a short time for XFER complete */ 1347 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE, 1348 1.2 ad SII_WAIT_COUNT, i); 1349 1.2 ad #ifdef DEBUG 1350 1.2 ad if (sii_debug > 4) 1351 1.2 ad printf("ds %x i %d\n", dstat, i); 1352 1.2 ad #endif 1353 1.2 ad /* just clear the DNE bit and check errors later */ 1354 1.2 ad if (dstat & SII_DNE) { 1355 1.2 ad regs->dstat = SII_DNE; 1356 1.2 ad wbflush(); 1357 1.2 ad } 1358 1.2 ad break; 1359 1.2 ad 1360 1.2 ad default: 1361 1.2 ad printf("%s: Couldn't handle phase %d... ignoring.\n", 1362 1.9 tsutsui device_xname(sc->sc_dev), dstat & SII_PHASE_MSK); 1363 1.2 ad } 1364 1.2 ad } 1365 1.2 ad 1366 1.2 ad #ifdef DEBUG 1367 1.2 ad if (sii_debug > 3) 1368 1.2 ad printf("\n"); 1369 1.2 ad #endif 1370 1.2 ad /* 1371 1.2 ad * Check to make sure we won't be interrupted again. 1372 1.2 ad * Deglitch dstat register. 1373 1.2 ad */ 1374 1.2 ad msg = regs->dstat; 1375 1.2 ad while (msg != (dstat = regs->dstat)) 1376 1.2 ad msg = dstat; 1377 1.2 ad if (dstat & (SII_CI | SII_DI)) 1378 1.2 ad goto again; 1379 1.2 ad 1380 1.2 ad if (sc->sc_target < 0) { 1381 1.2 ad /* look for another device that is ready */ 1382 1.2 ad for (i = 0; i < SII_NCMD; i++) { 1383 1.2 ad /* don't restart a disconnected command */ 1384 1.2 ad if (!sc->sc_cmd[i] || sc->sc_st[i].prevComm) 1385 1.2 ad continue; 1386 1.2 ad sii_StartCmd(sc, i); 1387 1.2 ad break; 1388 1.2 ad } 1389 1.2 ad } 1390 1.2 ad return; 1391 1.2 ad 1392 1.2 ad abort: 1393 1.2 ad /* jump here to abort the current command */ 1394 1.2 ad printf("%s: device %d: current command terminated\n", 1395 1.9 tsutsui device_xname(sc->sc_dev), sc->sc_target); 1396 1.2 ad #ifdef DEBUG 1397 1.2 ad sii_DumpLog(); 1398 1.2 ad #endif 1399 1.2 ad 1400 1.2 ad if ((cstat = regs->cstat) & SII_CON) { 1401 1.2 ad /* try to send an abort msg for awhile */ 1402 1.2 ad regs->dstat = SII_DNE; 1403 1.2 ad regs->data = MSG_ABORT; 1404 1.2 ad regs->comm = SII_INXFER | SII_ATN | (cstat & SII_STATE_MSK) | 1405 1.2 ad SII_MSG_OUT_PHASE; 1406 1.2 ad wbflush(); 1407 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, 1408 1.2 ad (dstat & (SII_DNE | SII_PHASE_MSK)) == 1409 1.2 ad (SII_DNE | SII_MSG_OUT_PHASE), 1410 1.2 ad 2 * SII_WAIT_COUNT, i); 1411 1.2 ad #ifdef DEBUG 1412 1.2 ad if (sii_debug > 0) 1413 1.2 ad printf("Abort: cs %x ds %x i %d\n", cstat, dstat, i); 1414 1.2 ad #endif 1415 1.2 ad if ((dstat & (SII_DNE | SII_PHASE_MSK)) == 1416 1.2 ad (SII_DNE | SII_MSG_OUT_PHASE)) { 1417 1.2 ad /* disconnect if command in progress */ 1418 1.2 ad regs->comm = SII_DISCON; 1419 1.2 ad wbflush(); 1420 1.2 ad SII_WAIT_UNTIL(cstat, regs->cstat, 1421 1.2 ad !(cstat & SII_CON), SII_WAIT_COUNT, i); 1422 1.2 ad } 1423 1.2 ad } else { 1424 1.2 ad #ifdef DEBUG 1425 1.2 ad if (sii_debug > 0) 1426 1.2 ad printf("Abort: cs %x\n", cstat); 1427 1.2 ad #endif 1428 1.2 ad } 1429 1.2 ad regs->cstat = 0xffff; 1430 1.2 ad regs->dstat = 0xffff; 1431 1.2 ad regs->comm = 0; 1432 1.2 ad wbflush(); 1433 1.2 ad 1434 1.2 ad i = sc->sc_target; 1435 1.2 ad sc->sc_target = -1; 1436 1.2 ad sii_CmdDone(sc, i, EIO); 1437 1.2 ad #ifdef DEBUG 1438 1.2 ad if (sii_debug > 4) 1439 1.2 ad printf("sii_DoIntr: after CmdDone target %d\n", sc->sc_target); 1440 1.2 ad #endif 1441 1.2 ad } 1442 1.2 ad 1443 1.2 ad static void 1444 1.6 dsl sii_StateChg(struct siisoftc *sc, u_int cstat) 1445 1.2 ad { 1446 1.2 ad SIIRegs *regs = sc->sc_regs; 1447 1.2 ad State *state; 1448 1.2 ad int i; 1449 1.2 ad 1450 1.2 ad #ifdef DEBUG 1451 1.2 ad if (sii_debug > 4) 1452 1.2 ad printf("SCH: "); 1453 1.2 ad #endif 1454 1.2 ad 1455 1.2 ad switch (cstat & SII_STATE_MSK) { 1456 1.2 ad case 0: 1457 1.2 ad /* disconnect */ 1458 1.2 ad i = sc->sc_target; 1459 1.2 ad sc->sc_target = -1; 1460 1.2 ad #ifdef DEBUG 1461 1.2 ad if (sii_debug > 4) 1462 1.2 ad printf("disconn %d ", i); 1463 1.2 ad #endif 1464 1.2 ad if (i >= 0 && !sc->sc_st[i].prevComm) { 1465 1.2 ad printf("%s: device %d: spurrious disconnect (%d)\n", 1466 1.9 tsutsui device_xname(sc->sc_dev), i, regs->slcsr); 1467 1.2 ad sc->sc_st[i].prevComm = 0; 1468 1.2 ad } 1469 1.2 ad break; 1470 1.2 ad 1471 1.2 ad case SII_CON: 1472 1.2 ad /* connected as initiator */ 1473 1.2 ad i = regs->slcsr; 1474 1.2 ad if (sc->sc_target == i) 1475 1.2 ad break; 1476 1.2 ad printf("%s: device %d: connect to device %d??\n", 1477 1.9 tsutsui device_xname(sc->sc_dev), sc->sc_target, i); 1478 1.2 ad sc->sc_target = i; 1479 1.2 ad break; 1480 1.2 ad 1481 1.2 ad case SII_DST: 1482 1.2 ad /* 1483 1.2 ad * Wait for CON to become valid, 1484 1.2 ad * chip is slow sometimes. 1485 1.2 ad */ 1486 1.2 ad SII_WAIT_UNTIL(cstat, regs->cstat, 1487 1.2 ad cstat & SII_CON, SII_WAIT_COUNT, i); 1488 1.2 ad if (!(cstat & SII_CON)) 1489 1.2 ad panic("sii resel"); 1490 1.2 ad /* FALLTHROUGH */ 1491 1.2 ad 1492 1.2 ad case SII_CON | SII_DST: 1493 1.2 ad /* 1494 1.2 ad * Its a reselection. Save the ID and wait for 1495 1.2 ad * interrupts to tell us what to do next 1496 1.2 ad * (should be MSG_IN of IDENTIFY). 1497 1.2 ad * NOTE: sc_target may be >= 0 if we were in 1498 1.2 ad * the process of trying to start a command 1499 1.2 ad * and were reselected before the select 1500 1.2 ad * command finished. 1501 1.2 ad */ 1502 1.2 ad sc->sc_target = i = regs->destat; 1503 1.2 ad state = &sc->sc_st[i]; 1504 1.2 ad regs->comm = SII_CON | SII_DST | SII_MSG_IN_PHASE; 1505 1.2 ad regs->dmctrl = state->dmaReqAck; 1506 1.2 ad wbflush(); 1507 1.2 ad if (!state->prevComm) { 1508 1.2 ad printf("%s: device %d: spurious reselection\n", 1509 1.9 tsutsui device_xname(sc->sc_dev), i); 1510 1.2 ad break; 1511 1.2 ad } 1512 1.2 ad state->prevComm = 0; 1513 1.2 ad #ifdef DEBUG 1514 1.2 ad if (sii_debug > 4) 1515 1.2 ad printf("resel %d ", sc->sc_target); 1516 1.2 ad #endif 1517 1.2 ad break; 1518 1.2 ad 1519 1.2 ad #ifdef notyet 1520 1.2 ad case SII_DST | SII_TGT: 1521 1.2 ad case SII_CON | SII_DST | SII_TGT: 1522 1.2 ad /* connected as target */ 1523 1.2 ad printf("%s: Selected by device %d as target!!\n", 1524 1.9 tsutsui device_xname(sc->sc_dev), regs->destat); 1525 1.2 ad regs->comm = SII_DISCON; 1526 1.2 ad wbflush(); 1527 1.2 ad SII_WAIT_UNTIL(!(regs->cstat & SII_CON), 1528 1.2 ad SII_WAIT_COUNT, i); 1529 1.2 ad regs->cstat = 0xffff; 1530 1.2 ad regs->dstat = 0xffff; 1531 1.2 ad regs->comm = 0; 1532 1.2 ad break; 1533 1.2 ad #endif 1534 1.2 ad 1535 1.2 ad default: 1536 1.2 ad printf("%s: Unknown state change (cs %x)!!\n", 1537 1.9 tsutsui device_xname(sc->sc_dev), cstat); 1538 1.2 ad #ifdef DEBUG 1539 1.2 ad sii_DumpLog(); 1540 1.2 ad #endif 1541 1.2 ad } 1542 1.2 ad } 1543 1.2 ad 1544 1.2 ad /* 1545 1.2 ad * Read one byte of data. 1546 1.2 ad * If 'ack' is true, acknowledge the byte. 1547 1.2 ad */ 1548 1.2 ad static int 1549 1.7 dsl sii_GetByte(SIIRegs *regs, int phase, int ack) 1550 1.2 ad { 1551 1.2 ad u_int dstat; 1552 1.2 ad u_int state; 1553 1.2 ad int i; 1554 1.2 ad int data; 1555 1.2 ad 1556 1.2 ad dstat = regs->dstat; 1557 1.2 ad state = regs->cstat & SII_STATE_MSK; 1558 1.2 ad i = -1; 1559 1.2 ad if (!(dstat & SII_IBF) || (dstat & SII_MIS)) { 1560 1.2 ad regs->comm = state | phase; 1561 1.2 ad wbflush(); 1562 1.2 ad /* wait a short time for IBF */ 1563 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_IBF, 1564 1.2 ad SII_WAIT_COUNT, i); 1565 1.2 ad #ifdef DEBUG 1566 1.2 ad if (!(dstat & SII_IBF)) 1567 1.2 ad printf("status no IBF\n"); 1568 1.2 ad #endif 1569 1.2 ad } 1570 1.2 ad if (dstat & SII_DNE) { /* XXX */ 1571 1.2 ad printf("sii_GetByte: DNE set 5\n"); 1572 1.2 ad #ifdef DEBUG 1573 1.2 ad sii_DumpLog(); 1574 1.2 ad #endif 1575 1.2 ad regs->dstat = SII_DNE; 1576 1.2 ad } 1577 1.2 ad data = regs->data; 1578 1.2 ad /* check for parity error */ 1579 1.2 ad if (dstat & SII_IPE) { 1580 1.2 ad #ifdef DEBUG 1581 1.2 ad if (sii_debug > 4) 1582 1.2 ad printf("cnt0 %d\n", i); 1583 1.2 ad #endif 1584 1.2 ad printf("sii_GetByte: data %x ?? ds %x cm %x i %d\n", 1585 1.2 ad data, dstat, regs->comm, i); /* XXX */ 1586 1.2 ad data = -1; 1587 1.2 ad ack = 1; 1588 1.2 ad } 1589 1.2 ad 1590 1.2 ad if (ack) { 1591 1.2 ad regs->comm = SII_INXFER | state | phase; 1592 1.2 ad wbflush(); 1593 1.2 ad 1594 1.2 ad /* wait a short time for XFER complete */ 1595 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE, 1596 1.2 ad SII_WAIT_COUNT, i); 1597 1.2 ad 1598 1.2 ad /* clear the DNE */ 1599 1.2 ad if (dstat & SII_DNE) { 1600 1.2 ad regs->dstat = SII_DNE; 1601 1.2 ad wbflush(); 1602 1.2 ad } 1603 1.2 ad } 1604 1.2 ad 1605 1.2 ad return (data); 1606 1.2 ad } 1607 1.2 ad 1608 1.2 ad /* 1609 1.2 ad * Exchange messages to initiate synchronous data transfers. 1610 1.2 ad */ 1611 1.2 ad static void 1612 1.6 dsl sii_DoSync(SIIRegs *regs, State *state) 1613 1.2 ad { 1614 1.2 ad u_int dstat, comm; 1615 1.2 ad int i, j; 1616 1.2 ad u_int len; 1617 1.2 ad 1618 1.2 ad #ifdef DEBUG 1619 1.2 ad if (sii_debug) 1620 1.2 ad printf("sii_DoSync: len %d per %d req/ack %d\n", 1621 1.2 ad sii_buf[1], sii_buf[3], sii_buf[4]); 1622 1.2 ad #endif 1623 1.2 ad 1624 1.2 ad /* SII chip can only handle a minimum transfer period of ??? */ 1625 1.2 ad if (sii_buf[3] < 64) 1626 1.2 ad sii_buf[3] = 64; 1627 1.2 ad /* SII chip can only handle a maximum REQ/ACK offset of 3 */ 1628 1.2 ad len = sii_buf[4]; 1629 1.2 ad if (len > 3) 1630 1.2 ad len = 3; 1631 1.2 ad 1632 1.2 ad sii_buf[0] = MSG_EXTENDED; 1633 1.2 ad sii_buf[1] = MSG_EXT_SDTR_LEN; 1634 1.2 ad sii_buf[2] = MSG_EXT_SDTR; 1635 1.2 ad sii_buf[4] = len; 1636 1.2 ad #if 1 1637 1.2 ad comm = SII_INXFER | SII_ATN | SII_MSG_OUT_PHASE | 1638 1.2 ad (regs->cstat & SII_STATE_MSK); 1639 1.2 ad regs->comm = comm & ~SII_INXFER; 1640 1.2 ad for (j = 0; j < 5; j++) { 1641 1.2 ad /* wait for target to request the next byte */ 1642 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_TBE, 1643 1.2 ad SII_WAIT_COUNT, i); 1644 1.2 ad if (!(dstat & SII_TBE) || 1645 1.2 ad (dstat & SII_PHASE_MSK) != SII_MSG_OUT_PHASE) { 1646 1.2 ad printf("sii_DoSync: TBE? ds %x cm %x i %d\n", 1647 1.2 ad dstat, comm, i); /* XXX */ 1648 1.2 ad return; 1649 1.2 ad } 1650 1.2 ad 1651 1.2 ad /* the last message byte should have ATN off */ 1652 1.2 ad if (j == 4) 1653 1.2 ad comm &= ~SII_ATN; 1654 1.2 ad 1655 1.2 ad regs->data = sii_buf[j]; 1656 1.2 ad regs->comm = comm; 1657 1.2 ad wbflush(); 1658 1.2 ad 1659 1.2 ad /* wait a short time for XFER complete */ 1660 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE, 1661 1.2 ad SII_WAIT_COUNT, i); 1662 1.2 ad 1663 1.2 ad if (!(dstat & SII_DNE)) { 1664 1.2 ad printf("sii_DoSync: DNE? ds %x cm %x i %d\n", 1665 1.2 ad dstat, comm, i); /* XXX */ 1666 1.2 ad return; 1667 1.2 ad } 1668 1.2 ad 1669 1.2 ad /* clear the DNE, other errors handled later */ 1670 1.2 ad regs->dstat = SII_DNE; 1671 1.2 ad wbflush(); 1672 1.2 ad } 1673 1.2 ad #else /* 0 */ 1674 1.2 ad sc->sii_copytobuf((u_short *)sii_buf, 1675 1.2 ad (volatile u_short *)SII_BUF_ADDR(sc), 5); 1676 1.2 ad printf("sii_DoSync: %x %x %x ds %x\n", 1677 1.2 ad ((volatile u_short *)SII_BUF_ADDR(sc))[0], 1678 1.2 ad ((volatile u_short *)SII_BUF_ADDR(sc))[2], 1679 1.2 ad ((volatile u_short *)SII_BUF_ADDR(sc))[4], 1680 1.2 ad regs->dstat); /* XXX */ 1681 1.2 ad regs->dmaddrl = (u_short)(SII_BUF_ADDR(sc) >> 1); 1682 1.2 ad regs->dmaddrh = (u_short)(SII_BUF_ADDR(sc) >> 17) & 03; 1683 1.2 ad regs->dmlotc = 5; 1684 1.2 ad regs->comm = SII_DMA | SII_INXFER | SII_ATN | 1685 1.2 ad (regs->cstat & SII_STATE_MSK) | SII_MSG_OUT_PHASE; 1686 1.2 ad wbflush(); 1687 1.2 ad 1688 1.2 ad /* wait a short time for XFER complete */ 1689 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, 1690 1.2 ad (dstat & (SII_DNE | SII_TCZ)) == (SII_DNE | SII_TCZ), 1691 1.2 ad SII_WAIT_COUNT, i); 1692 1.2 ad 1693 1.2 ad if ((dstat & (SII_DNE | SII_TCZ)) != (SII_DNE | SII_TCZ)) { 1694 1.2 ad printf("sii_DoSync: ds %x cm %x i %d lotc %d\n", 1695 1.2 ad dstat, regs->comm, i, regs->dmlotc); /* XXX */ 1696 1.2 ad sii_DumpLog(); /* XXX */ 1697 1.2 ad return; 1698 1.2 ad } 1699 1.2 ad /* clear the DNE, other errors handled later */ 1700 1.2 ad regs->dstat = SII_DNE; 1701 1.2 ad wbflush(); 1702 1.2 ad #endif /* 0 */ 1703 1.2 ad 1704 1.2 ad #if 0 1705 1.2 ad SII_WAIT_UNTIL(dstat, regs->dstat, dstat & (SII_CI | SII_DI), 1706 1.2 ad SII_WAIT_COUNT, i); 1707 1.2 ad printf("sii_DoSync: ds %x cm %x i %d lotc %d\n", 1708 1.2 ad dstat, regs->comm, i, regs->dmlotc); /* XXX */ 1709 1.2 ad #endif 1710 1.2 ad 1711 1.2 ad state->dmaReqAck = len; 1712 1.2 ad } 1713 1.2 ad 1714 1.2 ad /* 1715 1.2 ad * Issue the sequence of commands to the controller to start DMA. 1716 1.2 ad * NOTE: the data buffer should be word-aligned for DMA out. 1717 1.2 ad */ 1718 1.2 ad static void 1719 1.7 dsl sii_StartDMA(SIIRegs *regs, int phase, u_short *dmaAddr, int size) 1720 1.7 dsl /* regs: which SII to use */ 1721 1.7 dsl /* phase: phase to send/receive data */ 1722 1.7 dsl /* dmaAddr: DMA buffer address */ 1723 1.7 dsl /* size: # of bytes to transfer */ 1724 1.2 ad { 1725 1.2 ad 1726 1.2 ad if (regs->dstat & SII_DNE) { /* XXX */ 1727 1.2 ad regs->dstat = SII_DNE; 1728 1.2 ad printf("sii_StartDMA: DNE set\n"); 1729 1.2 ad #ifdef DEBUG 1730 1.2 ad sii_DumpLog(); 1731 1.2 ad #endif 1732 1.2 ad } 1733 1.2 ad regs->dmaddrl = ((u_long)dmaAddr >> 1); 1734 1.2 ad regs->dmaddrh = ((u_long)dmaAddr >> 17) & 03; 1735 1.2 ad regs->dmlotc = size; 1736 1.2 ad regs->comm = SII_DMA | SII_INXFER | (regs->cstat & SII_STATE_MSK) | 1737 1.2 ad phase; 1738 1.2 ad wbflush(); 1739 1.2 ad 1740 1.2 ad #ifdef DEBUG 1741 1.2 ad if (sii_debug > 5) { 1742 1.2 ad printf("sii_StartDMA: cs 0x%x, ds 0x%x, cm 0x%x, size %d\n", 1743 1.2 ad regs->cstat, regs->dstat, regs->comm, size); 1744 1.2 ad } 1745 1.2 ad #endif 1746 1.2 ad } 1747 1.2 ad 1748 1.2 ad /* 1749 1.2 ad * Call the device driver's 'done' routine to let it know the command is done. 1750 1.2 ad * The 'done' routine may try to start another command. 1751 1.2 ad * To be fair, we should start pending commands for other devices 1752 1.2 ad * before allowing the same device to start another command. 1753 1.2 ad */ 1754 1.2 ad static void 1755 1.7 dsl sii_CmdDone(struct siisoftc *sc, int target, int error) 1756 1.7 dsl /* sc: which SII to use */ 1757 1.7 dsl /* target: which device is done */ 1758 1.7 dsl /* error: error code if any errors */ 1759 1.2 ad { 1760 1.2 ad int i; 1761 1.2 ad 1762 1.12 maya ScsiCmd *scsicmd __unused = sc->sc_cmd[target]; 1763 1.12 maya KASSERTMSG(target >= 0 && scsicmd, "sii_CmdDone"); 1764 1.2 ad sc->sc_cmd[target] = (ScsiCmd *)0; 1765 1.2 ad #ifdef DEBUG 1766 1.2 ad if (sii_debug > 1) { 1767 1.2 ad printf("sii_CmdDone: %s target %d cmd %x err %d resid %d\n", 1768 1.9 tsutsui device_xname(sc->sc_dev), 1769 1.9 tsutsui target, scsicmd->cmd[0], error, sc->sc_st[target].buflen); 1770 1.2 ad } 1771 1.2 ad #endif 1772 1.2 ad 1773 1.2 ad /* look for another device that is ready */ 1774 1.2 ad for (i = 0; i < SII_NCMD; i++) { 1775 1.2 ad /* don't restart a disconnected command */ 1776 1.2 ad if (!sc->sc_cmd[i] || sc->sc_st[i].prevComm) 1777 1.2 ad continue; 1778 1.2 ad sii_StartCmd(sc, i); 1779 1.2 ad break; 1780 1.2 ad } 1781 1.2 ad 1782 1.2 ad sc->sc_xs[target]->status = sc->sc_st[target].statusByte; 1783 1.2 ad /* 1784 1.2 ad * Convert SII driver error code to MI SCSI XS_*. 1785 1.2 ad */ 1786 1.2 ad switch (error) { 1787 1.2 ad case 0: 1788 1.2 ad sc->sc_xs[target]->error = XS_NOERROR; 1789 1.2 ad break; 1790 1.2 ad case ENXIO: 1791 1.2 ad sc->sc_xs[target]->error = XS_SELTIMEOUT; 1792 1.2 ad break; 1793 1.2 ad case EBUSY: 1794 1.2 ad sc->sc_xs[target]->error = XS_BUSY; 1795 1.2 ad break; 1796 1.2 ad case EIO: 1797 1.2 ad sc->sc_xs[target]->error = XS_DRIVER_STUFFUP; 1798 1.2 ad break; 1799 1.2 ad default: 1800 1.2 ad sc->sc_xs[target]->error = XS_DRIVER_STUFFUP; 1801 1.2 ad } 1802 1.2 ad sc->sc_xs[target]->resid = sc->sc_st[target].buflen; 1803 1.2 ad scsipi_done(sc->sc_xs[target]); 1804 1.2 ad } 1805 1.2 ad 1806 1.2 ad #ifdef DEBUG 1807 1.2 ad static void 1808 1.8 cegger sii_DumpLog(void) 1809 1.2 ad { 1810 1.2 ad struct sii_log *lp; 1811 1.2 ad 1812 1.2 ad printf("sii: cmd %x bn %d cnt %d\n", sii_debug_cmd, sii_debug_bn, 1813 1.2 ad sii_debug_sz); 1814 1.2 ad lp = sii_logp; 1815 1.2 ad do { 1816 1.2 ad printf("target %d cs %x ds %x cm %x msg %x rlen %x dlen %x\n", 1817 1.2 ad lp->target, lp->cstat, lp->dstat, lp->comm, lp->msg, 1818 1.2 ad lp->rlen, lp->dlen); 1819 1.2 ad if (++lp >= &sii_log[NLOG]) 1820 1.2 ad lp = sii_log; 1821 1.2 ad } while (lp != sii_logp); 1822 1.2 ad } 1823 1.2 ad #endif 1824