1 /* $NetBSD: mesh.c,v 1.25 2006/03/29 04:16:45 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 Tsubai Masanari. 5 * Copyright (c) 1999 Internet Research Institute, Inc. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by 19 * Internet Research Institute, Inc. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: mesh.c,v 1.25 2006/03/29 04:16:45 thorpej Exp $"); 37 38 #include <sys/param.h> 39 #include <sys/buf.h> 40 #include <sys/device.h> 41 #include <sys/errno.h> 42 #include <sys/kernel.h> 43 #include <sys/malloc.h> 44 #include <sys/queue.h> 45 #include <sys/systm.h> 46 47 #include <uvm/uvm_extern.h> 48 49 #include <dev/scsipi/scsi_all.h> 50 #include <dev/scsipi/scsipi_all.h> 51 #include <dev/scsipi/scsiconf.h> 52 #include <dev/scsipi/scsi_message.h> 53 54 #include <dev/ofw/openfirm.h> 55 56 #include <machine/autoconf.h> 57 #include <machine/cpu.h> 58 #include <machine/pio.h> 59 60 #include <macppc/dev/dbdma.h> 61 #include <macppc/dev/meshreg.h> 62 63 #ifdef MESH_DEBUG 64 # define DPRINTF printf 65 #else 66 # define DPRINTF while (0) printf 67 #endif 68 69 #define T_SYNCMODE 0x01 /* target uses sync mode */ 70 #define T_SYNCNEGO 0x02 /* sync negotiation done */ 71 72 struct mesh_tinfo { 73 int flags; 74 int period; 75 int offset; 76 }; 77 78 /* scb flags */ 79 #define MESH_POLL 0x01 80 #define MESH_CHECK 0x02 81 #define MESH_READ 0x80 82 83 struct mesh_scb { 84 TAILQ_ENTRY(mesh_scb) chain; 85 int flags; 86 struct scsipi_xfer *xs; 87 struct scsipi_generic cmd; 88 int cmdlen; 89 int target; /* target SCSI ID */ 90 int resid; 91 vaddr_t daddr; 92 vsize_t dlen; 93 int status; 94 }; 95 96 /* sc_flags value */ 97 #define MESH_DMA_ACTIVE 0x01 98 99 struct mesh_softc { 100 struct device sc_dev; /* us as a device */ 101 struct scsipi_channel sc_channel; 102 struct scsipi_adapter sc_adapter; 103 104 u_char *sc_reg; /* MESH base address */ 105 dbdma_regmap_t *sc_dmareg; /* DMA register address */ 106 dbdma_command_t *sc_dmacmd; /* DMA command area */ 107 108 int sc_flags; 109 int sc_cfflags; /* copy of config flags */ 110 int sc_meshid; /* MESH version */ 111 int sc_minsync; /* minimum sync period */ 112 int sc_irq; 113 int sc_freq; /* SCSI bus frequency in MHz */ 114 int sc_id; /* our SCSI ID */ 115 struct mesh_tinfo sc_tinfo[8]; /* target information */ 116 117 int sc_nextstate; 118 int sc_prevphase; 119 struct mesh_scb *sc_nexus; /* current command */ 120 121 int sc_msgout; 122 int sc_imsglen; 123 u_char sc_imsg[16]; 124 u_char sc_omsg[16]; 125 126 TAILQ_HEAD(, mesh_scb) free_scb; 127 TAILQ_HEAD(, mesh_scb) ready_scb; 128 struct mesh_scb sc_scb[16]; 129 }; 130 131 /* mesh_msgout() values */ 132 #define SEND_REJECT 1 133 #define SEND_IDENTIFY 2 134 #define SEND_SDTR 4 135 136 static inline int mesh_read_reg __P((struct mesh_softc *, int)); 137 static inline void mesh_set_reg __P((struct mesh_softc *, int, int)); 138 139 int mesh_match __P((struct device *, struct cfdata *, void *)); 140 void mesh_attach __P((struct device *, struct device *, void *)); 141 void mesh_shutdownhook __P((void *)); 142 int mesh_intr __P((void *)); 143 void mesh_error __P((struct mesh_softc *, struct mesh_scb *, int, int)); 144 void mesh_select __P((struct mesh_softc *, struct mesh_scb *)); 145 void mesh_identify __P((struct mesh_softc *, struct mesh_scb *)); 146 void mesh_command __P((struct mesh_softc *, struct mesh_scb *)); 147 void mesh_dma_setup __P((struct mesh_softc *, struct mesh_scb *)); 148 void mesh_dataio __P((struct mesh_softc *, struct mesh_scb *)); 149 void mesh_status __P((struct mesh_softc *, struct mesh_scb *)); 150 void mesh_msgin __P((struct mesh_softc *, struct mesh_scb *)); 151 void mesh_msgout __P((struct mesh_softc *, int)); 152 void mesh_bus_reset __P((struct mesh_softc *)); 153 void mesh_reset __P((struct mesh_softc *)); 154 int mesh_stp __P((struct mesh_softc *, int)); 155 void mesh_setsync __P((struct mesh_softc *, struct mesh_tinfo *)); 156 struct mesh_scb *mesh_get_scb __P((struct mesh_softc *)); 157 void mesh_free_scb __P((struct mesh_softc *, struct mesh_scb *)); 158 void mesh_scsi_request __P((struct scsipi_channel *, 159 scsipi_adapter_req_t, void *)); 160 void mesh_sched __P((struct mesh_softc *)); 161 int mesh_poll __P((struct mesh_softc *, struct scsipi_xfer *)); 162 void mesh_done __P((struct mesh_softc *, struct mesh_scb *)); 163 void mesh_timeout __P((void *)); 164 void mesh_minphys __P((struct buf *)); 165 166 167 #define MESH_DATAOUT 0 168 #define MESH_DATAIN MESH_STATUS0_IO 169 #define MESH_COMMAND MESH_STATUS0_CD 170 #define MESH_STATUS (MESH_STATUS0_CD | MESH_STATUS0_IO) 171 #define MESH_MSGOUT (MESH_STATUS0_MSG | MESH_STATUS0_CD) 172 #define MESH_MSGIN (MESH_STATUS0_MSG | MESH_STATUS0_CD | MESH_STATUS0_IO) 173 174 #define MESH_SELECTING 8 175 #define MESH_IDENTIFY 9 176 #define MESH_COMPLETE 10 177 #define MESH_BUSFREE 11 178 #define MESH_UNKNOWN -1 179 180 #define MESH_PHASE_MASK (MESH_STATUS0_MSG | MESH_STATUS0_CD | MESH_STATUS0_IO) 181 182 CFATTACH_DECL(mesh, sizeof(struct mesh_softc), 183 mesh_match, mesh_attach, NULL, NULL); 184 185 int 186 mesh_match(parent, cf, aux) 187 struct device *parent; 188 struct cfdata *cf; 189 void *aux; 190 { 191 struct confargs *ca = aux; 192 char compat[32]; 193 194 if (strcmp(ca->ca_name, "mesh") == 0) 195 return 1; 196 197 memset(compat, 0, sizeof(compat)); 198 OF_getprop(ca->ca_node, "compatible", compat, sizeof(compat)); 199 if (strcmp(compat, "chrp,mesh0") == 0) 200 return 1; 201 202 return 0; 203 } 204 205 void 206 mesh_attach(parent, self, aux) 207 struct device *parent, *self; 208 void *aux; 209 { 210 struct mesh_softc *sc = (void *)self; 211 struct confargs *ca = aux; 212 int i; 213 u_int *reg; 214 215 reg = ca->ca_reg; 216 reg[0] += ca->ca_baseaddr; 217 reg[2] += ca->ca_baseaddr; 218 sc->sc_reg = mapiodev(reg[0], reg[1]); 219 sc->sc_irq = ca->ca_intr[0]; 220 sc->sc_dmareg = mapiodev(reg[2], reg[3]); 221 222 sc->sc_cfflags = device_cfdata(self)->cf_flags; 223 sc->sc_meshid = mesh_read_reg(sc, MESH_MESH_ID) & 0x1f; 224 #if 0 225 if (sc->sc_meshid != (MESH_SIGNATURE & 0x1f) { 226 printf(": unknown MESH ID (0x%x)\n", sc->sc_meshid); 227 return; 228 } 229 #endif 230 if (OF_getprop(ca->ca_node, "clock-frequency", &sc->sc_freq, 4) != 4) { 231 printf(": cannot get clock-frequency\n"); 232 return; 233 } 234 sc->sc_freq /= 1000000; /* in MHz */ 235 sc->sc_minsync = 25; /* maximum sync rate = 10MB/sec */ 236 sc->sc_id = 7; 237 238 TAILQ_INIT(&sc->free_scb); 239 TAILQ_INIT(&sc->ready_scb); 240 for (i = 0; i < sizeof(sc->sc_scb)/sizeof(sc->sc_scb[0]); i++) 241 TAILQ_INSERT_TAIL(&sc->free_scb, &sc->sc_scb[i], chain); 242 243 sc->sc_dmacmd = dbdma_alloc(sizeof(dbdma_command_t) * 20); 244 245 mesh_reset(sc); 246 mesh_bus_reset(sc); 247 248 printf(" irq %d: %dMHz, SCSI ID %d\n", 249 sc->sc_irq, sc->sc_freq, sc->sc_id); 250 251 sc->sc_adapter.adapt_dev = &sc->sc_dev; 252 sc->sc_adapter.adapt_nchannels = 1; 253 sc->sc_adapter.adapt_openings = 7; 254 sc->sc_adapter.adapt_max_periph = 1; 255 sc->sc_adapter.adapt_ioctl = NULL; 256 sc->sc_adapter.adapt_minphys = mesh_minphys; 257 sc->sc_adapter.adapt_request = mesh_scsi_request; 258 259 sc->sc_channel.chan_adapter = &sc->sc_adapter; 260 sc->sc_channel.chan_bustype = &scsi_bustype; 261 sc->sc_channel.chan_channel = 0; 262 sc->sc_channel.chan_ntargets = 8; 263 sc->sc_channel.chan_nluns = 8; 264 sc->sc_channel.chan_id = sc->sc_id; 265 266 config_found(&sc->sc_dev, &sc->sc_channel, scsiprint); 267 268 intr_establish(sc->sc_irq, IST_LEVEL, IPL_BIO, mesh_intr, sc); 269 270 /* Reset SCSI bus when halt. */ 271 shutdownhook_establish(mesh_shutdownhook, sc); 272 } 273 274 #define MESH_SET_XFER(sc, count) do { \ 275 mesh_set_reg(sc, MESH_XFER_COUNT0, count); \ 276 mesh_set_reg(sc, MESH_XFER_COUNT1, count >> 8); \ 277 } while (0) 278 279 #define MESH_GET_XFER(sc) ((mesh_read_reg(sc, MESH_XFER_COUNT1) << 8) | \ 280 mesh_read_reg(sc, MESH_XFER_COUNT0)) 281 282 int 283 mesh_read_reg(sc, reg) 284 struct mesh_softc *sc; 285 int reg; 286 { 287 return in8(sc->sc_reg + reg); 288 } 289 290 void 291 mesh_set_reg(sc, reg, val) 292 struct mesh_softc *sc; 293 int reg, val; 294 { 295 out8(sc->sc_reg + reg, val); 296 } 297 298 void 299 mesh_shutdownhook(arg) 300 void *arg; 301 { 302 struct mesh_softc *sc = arg; 303 304 /* Set to async mode. */ 305 mesh_set_reg(sc, MESH_SYNC_PARAM, 2); 306 mesh_bus_reset(sc); 307 } 308 309 #ifdef MESH_DEBUG 310 static char scsi_phase[][8] = { 311 "DATAOUT", 312 "DATAIN", 313 "COMMAND", 314 "STATUS", 315 "", 316 "", 317 "MSGOUT", 318 "MSGIN" 319 }; 320 #endif 321 322 int 323 mesh_intr(arg) 324 void *arg; 325 { 326 struct mesh_softc *sc = arg; 327 struct mesh_scb *scb; 328 int fifocnt; 329 u_char intr, exception, error, status0, status1; 330 331 intr = mesh_read_reg(sc, MESH_INTERRUPT); 332 if (intr == 0) { 333 DPRINTF("%s: stray interrupt\n", sc->sc_dev.dv_xname); 334 return 0; 335 } 336 337 exception = mesh_read_reg(sc, MESH_EXCEPTION); 338 error = mesh_read_reg(sc, MESH_ERROR); 339 status0 = mesh_read_reg(sc, MESH_BUS_STATUS0); 340 status1 = mesh_read_reg(sc, MESH_BUS_STATUS1); 341 342 /* clear interrupt */ 343 mesh_set_reg(sc, MESH_INTERRUPT, intr); 344 345 #ifdef MESH_DEBUG 346 { 347 char buf1[64], buf2[64]; 348 349 bitmask_snprintf(status0, MESH_STATUS0_BITMASK, buf1, sizeof buf1); 350 bitmask_snprintf(exception, MESH_EXC_BITMASK, buf2, sizeof buf2); 351 printf("mesh_intr status0 = 0x%s (%s), exc = 0x%s\n", 352 buf1, scsi_phase[status0 & 7], buf2); 353 } 354 #endif 355 356 scb = sc->sc_nexus; 357 if (scb == NULL) { 358 DPRINTF("%s: NULL nexus\n", sc->sc_dev.dv_xname); 359 return 1; 360 } 361 362 if (intr & MESH_INTR_CMDDONE) { 363 if (sc->sc_flags & MESH_DMA_ACTIVE) { 364 dbdma_stop(sc->sc_dmareg); 365 366 sc->sc_flags &= ~MESH_DMA_ACTIVE; 367 scb->resid = MESH_GET_XFER(sc); 368 369 fifocnt = mesh_read_reg(sc, MESH_FIFO_COUNT); 370 if (fifocnt != 0) { 371 if (scb->flags & MESH_READ) { 372 char *cp; 373 374 cp = (char *)scb->daddr + scb->dlen 375 - fifocnt; 376 DPRINTF("fifocnt = %d, resid = %d\n", 377 fifocnt, scb->resid); 378 while (fifocnt > 0) { 379 *cp++ = mesh_read_reg(sc, 380 MESH_FIFO); 381 fifocnt--; 382 } 383 } else { 384 mesh_set_reg(sc, MESH_SEQUENCE, 385 MESH_CMD_FLUSH_FIFO); 386 } 387 } else { 388 /* Clear all interrupts */ 389 mesh_set_reg(sc, MESH_INTERRUPT, 7); 390 } 391 } 392 } 393 394 if (intr & MESH_INTR_ERROR) { 395 printf("%s: error %02x %02x\n", 396 sc->sc_dev.dv_xname, error, exception); 397 mesh_error(sc, scb, error, 0); 398 return 1; 399 } 400 401 if (intr & MESH_INTR_EXCEPTION) { 402 /* selection timeout */ 403 if (exception & MESH_EXC_SELTO) { 404 mesh_error(sc, scb, 0, exception); 405 return 1; 406 } 407 408 /* phase mismatch */ 409 if (exception & MESH_EXC_PHASEMM) { 410 DPRINTF("%s: PHASE MISMATCH; nextstate = %d -> ", 411 sc->sc_dev.dv_xname, sc->sc_nextstate); 412 sc->sc_nextstate = status0 & MESH_PHASE_MASK; 413 414 DPRINTF("%d, resid = %d\n", 415 sc->sc_nextstate, scb->resid); 416 } 417 } 418 419 if (sc->sc_nextstate == MESH_UNKNOWN) 420 sc->sc_nextstate = status0 & MESH_PHASE_MASK; 421 422 switch (sc->sc_nextstate) { 423 424 case MESH_IDENTIFY: 425 mesh_identify(sc, scb); 426 break; 427 case MESH_COMMAND: 428 mesh_command(sc, scb); 429 break; 430 case MESH_DATAIN: 431 case MESH_DATAOUT: 432 mesh_dataio(sc, scb); 433 break; 434 case MESH_STATUS: 435 mesh_status(sc, scb); 436 break; 437 case MESH_MSGIN: 438 mesh_msgin(sc, scb); 439 break; 440 case MESH_COMPLETE: 441 mesh_done(sc, scb); 442 break; 443 444 default: 445 printf("%s: unknown state (%d)\n", sc->sc_dev.dv_xname, 446 sc->sc_nextstate); 447 scb->xs->error = XS_DRIVER_STUFFUP; 448 mesh_done(sc, scb); 449 } 450 451 return 1; 452 } 453 454 void 455 mesh_error(sc, scb, error, exception) 456 struct mesh_softc *sc; 457 struct mesh_scb *scb; 458 int error, exception; 459 { 460 if (error & MESH_ERR_SCSI_RESET) { 461 printf("%s: SCSI RESET\n", sc->sc_dev.dv_xname); 462 463 /* Wait until the RST signal is deasserted. */ 464 while (mesh_read_reg(sc, MESH_BUS_STATUS1) & MESH_STATUS1_RST); 465 mesh_reset(sc); 466 return; 467 } 468 469 if (error & MESH_ERR_PARITY_ERR0) { 470 printf("%s: parity error\n", sc->sc_dev.dv_xname); 471 scb->xs->error = XS_DRIVER_STUFFUP; 472 } 473 474 if (error & MESH_ERR_DISCONNECT) { 475 printf("%s: unexpected disconnect\n", sc->sc_dev.dv_xname); 476 if (sc->sc_nextstate != MESH_COMPLETE) 477 scb->xs->error = XS_DRIVER_STUFFUP; 478 } 479 480 if (exception & MESH_EXC_SELTO) { 481 /* XXX should reset bus here? */ 482 scb->xs->error = XS_SELTIMEOUT; 483 } 484 485 mesh_done(sc, scb); 486 } 487 488 void 489 mesh_select(sc, scb) 490 struct mesh_softc *sc; 491 struct mesh_scb *scb; 492 { 493 struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target]; 494 int timeout; 495 496 DPRINTF("mesh_select\n"); 497 498 mesh_setsync(sc, ti); 499 MESH_SET_XFER(sc, 0); 500 501 /* arbitration */ 502 503 /* 504 * MESH mistakenly asserts TARGET ID bit along with its own ID bit 505 * in arbitration phase (like selection). So we should load 506 * initiator ID to DestID register temporarily. 507 */ 508 mesh_set_reg(sc, MESH_DEST_ID, sc->sc_id); 509 mesh_set_reg(sc, MESH_INTR_MASK, 0); /* disable intr. */ 510 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_ARBITRATE); 511 512 while (mesh_read_reg(sc, MESH_INTERRUPT) == 0); 513 mesh_set_reg(sc, MESH_INTERRUPT, 1); 514 mesh_set_reg(sc, MESH_INTR_MASK, 7); 515 516 /* selection */ 517 mesh_set_reg(sc, MESH_DEST_ID, scb->target); 518 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_SELECT | MESH_SEQ_ATN); 519 520 sc->sc_prevphase = MESH_SELECTING; 521 sc->sc_nextstate = MESH_IDENTIFY; 522 523 timeout = mstohz(scb->xs->timeout); 524 if (timeout == 0) 525 timeout = 1; 526 527 callout_reset(&scb->xs->xs_callout, timeout, mesh_timeout, scb); 528 } 529 530 void 531 mesh_identify(sc, scb) 532 struct mesh_softc *sc; 533 struct mesh_scb *scb; 534 { 535 struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target]; 536 537 DPRINTF("mesh_identify\n"); 538 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO); 539 540 if ((ti->flags & T_SYNCNEGO) == 0) { 541 ti->period = sc->sc_minsync; 542 ti->offset = 15; 543 mesh_msgout(sc, SEND_IDENTIFY | SEND_SDTR); 544 sc->sc_nextstate = MESH_MSGIN; 545 } else { 546 mesh_msgout(sc, SEND_IDENTIFY); 547 sc->sc_nextstate = MESH_COMMAND; 548 } 549 } 550 551 void 552 mesh_command(sc, scb) 553 struct mesh_softc *sc; 554 struct mesh_scb *scb; 555 { 556 int i; 557 char *cmdp; 558 559 #ifdef MESH_DEBUG 560 printf("mesh_command cdb = %02x", scb->cmd.opcode); 561 for (i = 0; i < 5; i++) 562 printf(" %02x", scb->cmd.bytes[i]); 563 printf("\n"); 564 #endif 565 566 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO); 567 568 MESH_SET_XFER(sc, scb->cmdlen); 569 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_COMMAND); 570 571 cmdp = (char *)&scb->cmd; 572 for (i = 0; i < scb->cmdlen; i++) 573 mesh_set_reg(sc, MESH_FIFO, *cmdp++); 574 575 if (scb->resid == 0) 576 sc->sc_nextstate = MESH_STATUS; /* no data xfer */ 577 else 578 sc->sc_nextstate = MESH_DATAIN; 579 } 580 581 void 582 mesh_dma_setup(sc, scb) 583 struct mesh_softc *sc; 584 struct mesh_scb *scb; 585 { 586 int datain = scb->flags & MESH_READ; 587 dbdma_command_t *cmdp; 588 u_int cmd; 589 vaddr_t va; 590 int count, offset; 591 592 cmdp = sc->sc_dmacmd; 593 cmd = datain ? DBDMA_CMD_IN_MORE : DBDMA_CMD_OUT_MORE; 594 595 count = scb->dlen; 596 597 if (count / PAGE_SIZE > 32) 598 panic("mesh: transfer size >= 128k"); 599 600 va = scb->daddr; 601 offset = va & PGOFSET; 602 603 /* if va is not page-aligned, setup the first page */ 604 if (offset != 0) { 605 int rest = PAGE_SIZE - offset; /* the rest in the page */ 606 607 if (count > rest) { /* if continues to next page */ 608 DBDMA_BUILD(cmdp, cmd, 0, rest, vtophys(va), 609 DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, 610 DBDMA_BRANCH_NEVER); 611 count -= rest; 612 va += rest; 613 cmdp++; 614 } 615 } 616 617 /* now va is page-aligned */ 618 while (count > PAGE_SIZE) { 619 DBDMA_BUILD(cmdp, cmd, 0, PAGE_SIZE, vtophys(va), 620 DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); 621 count -= PAGE_SIZE; 622 va += PAGE_SIZE; 623 cmdp++; 624 } 625 626 /* the last page (count <= PAGE_SIZE here) */ 627 cmd = datain ? DBDMA_CMD_IN_LAST : DBDMA_CMD_OUT_LAST; 628 DBDMA_BUILD(cmdp, cmd , 0, count, vtophys(va), 629 DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); 630 cmdp++; 631 632 DBDMA_BUILD(cmdp, DBDMA_CMD_STOP, 0, 0, 0, 633 DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); 634 } 635 636 void 637 mesh_dataio(sc, scb) 638 struct mesh_softc *sc; 639 struct mesh_scb *scb; 640 { 641 DPRINTF("mesh_dataio len = %ld (%s)\n", scb->dlen, 642 scb->flags & MESH_READ ? "read" : "write"); 643 644 mesh_dma_setup(sc, scb); 645 646 if (scb->dlen == 65536) 647 MESH_SET_XFER(sc, 0); /* TC = 0 means 64KB transfer */ 648 else 649 MESH_SET_XFER(sc, scb->dlen); 650 651 if (scb->flags & MESH_READ) 652 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_DATAIN | MESH_SEQ_DMA); 653 else 654 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_DATAOUT | MESH_SEQ_DMA); 655 dbdma_start(sc->sc_dmareg, sc->sc_dmacmd); 656 sc->sc_flags |= MESH_DMA_ACTIVE; 657 sc->sc_nextstate = MESH_STATUS; 658 } 659 660 void 661 mesh_status(sc, scb) 662 struct mesh_softc *sc; 663 struct mesh_scb *scb; 664 { 665 if (mesh_read_reg(sc, MESH_FIFO_COUNT) == 0) { /* XXX cheat */ 666 DPRINTF("mesh_status(0)\n"); 667 MESH_SET_XFER(sc, 1); 668 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_STATUS); 669 sc->sc_nextstate = MESH_STATUS; 670 return; 671 } 672 673 scb->status = mesh_read_reg(sc, MESH_FIFO); 674 DPRINTF("mesh_status(1): status = 0x%x\n", scb->status); 675 if (mesh_read_reg(sc, MESH_FIFO_COUNT) != 0) 676 DPRINTF("FIFO_COUNT=%d\n", mesh_read_reg(sc, MESH_FIFO_COUNT)); 677 678 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO); 679 MESH_SET_XFER(sc, 1); 680 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN); 681 682 sc->sc_nextstate = MESH_MSGIN; 683 } 684 685 void 686 mesh_msgin(sc, scb) 687 struct mesh_softc *sc; 688 struct mesh_scb *scb; 689 { 690 DPRINTF("mesh_msgin\n"); 691 692 if (mesh_read_reg(sc, MESH_FIFO_COUNT) == 0) { /* XXX cheat */ 693 MESH_SET_XFER(sc, 1); 694 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN); 695 sc->sc_imsglen = 0; 696 sc->sc_nextstate = MESH_MSGIN; 697 return; 698 } 699 700 sc->sc_imsg[sc->sc_imsglen++] = mesh_read_reg(sc, MESH_FIFO); 701 702 if (sc->sc_imsglen == 1 && MSG_IS1BYTE(sc->sc_imsg[0])) 703 goto gotit; 704 if (sc->sc_imsglen == 2 && MSG_IS2BYTE(sc->sc_imsg[0])) 705 goto gotit; 706 if (sc->sc_imsglen >= 3 && MSG_ISEXTENDED(sc->sc_imsg[0]) && 707 sc->sc_imsglen == sc->sc_imsg[1] + 2) 708 goto gotit; 709 710 sc->sc_nextstate = MESH_MSGIN; 711 MESH_SET_XFER(sc, 1); 712 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN); 713 return; 714 715 gotit: 716 #ifdef MESH_DEBUG 717 printf("msgin:"); 718 for (i = 0; i < sc->sc_imsglen; i++) 719 printf(" 0x%02x", sc->sc_imsg[i]); 720 printf("\n"); 721 #endif 722 723 switch (sc->sc_imsg[0]) { 724 case MSG_CMDCOMPLETE: 725 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE); 726 sc->sc_nextstate = MESH_COMPLETE; 727 sc->sc_imsglen = 0; 728 return; 729 730 case MSG_MESSAGE_REJECT: 731 if (sc->sc_msgout & SEND_SDTR) { 732 printf("SDTR rejected\n"); 733 printf("using async mode\n"); 734 sc->sc_tinfo[scb->target].period = 0; 735 sc->sc_tinfo[scb->target].offset = 0; 736 mesh_setsync(sc, &sc->sc_tinfo[scb->target]); 737 break; 738 } 739 break; 740 741 case MSG_NOOP: 742 break; 743 744 case MSG_EXTENDED: 745 goto extended_msg; 746 747 default: 748 scsipi_printaddr(scb->xs->xs_periph); 749 printf("unrecognized MESSAGE(0x%02x); sending REJECT\n", 750 sc->sc_imsg[0]); 751 752 reject: 753 mesh_msgout(sc, SEND_REJECT); 754 return; 755 } 756 goto done; 757 758 extended_msg: 759 /* process an extended message */ 760 switch (sc->sc_imsg[2]) { 761 case MSG_EXT_SDTR: 762 { 763 struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target]; 764 int period = sc->sc_imsg[3]; 765 int offset = sc->sc_imsg[4]; 766 int r = 250 / period; 767 int s = (100*250) / period - 100 * r; 768 769 if (period < sc->sc_minsync) { 770 ti->period = sc->sc_minsync; 771 ti->offset = 15; 772 mesh_msgout(sc, SEND_SDTR); 773 return; 774 } 775 scsipi_printaddr(scb->xs->xs_periph); 776 /* XXX if (offset != 0) ... */ 777 printf("max sync rate %d.%02dMb/s\n", r, s); 778 ti->period = period; 779 ti->offset = offset; 780 ti->flags |= T_SYNCNEGO; 781 ti->flags |= T_SYNCMODE; 782 mesh_setsync(sc, ti); 783 goto done; 784 } 785 default: 786 printf("%s target %d: rejecting extended message 0x%x\n", 787 sc->sc_dev.dv_xname, scb->target, sc->sc_imsg[0]); 788 goto reject; 789 } 790 791 done: 792 sc->sc_imsglen = 0; 793 sc->sc_nextstate = MESH_UNKNOWN; 794 795 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE); /* XXX really? */ 796 } 797 798 void 799 mesh_msgout(sc, msg) 800 struct mesh_softc *sc; 801 int msg; 802 { 803 struct mesh_scb *scb = sc->sc_nexus; 804 struct mesh_tinfo *ti; 805 int lun, len, i; 806 807 DPRINTF("mesh_msgout: sending"); 808 809 sc->sc_msgout = msg; 810 len = 0; 811 812 if (msg & SEND_REJECT) { 813 DPRINTF(" REJECT"); 814 sc->sc_omsg[len++] = MSG_MESSAGE_REJECT; 815 } 816 if (msg & SEND_IDENTIFY) { 817 DPRINTF(" IDENTIFY"); 818 lun = scb->xs->xs_periph->periph_lun; 819 sc->sc_omsg[len++] = MSG_IDENTIFY(lun, 0); 820 } 821 if (msg & SEND_SDTR) { 822 DPRINTF(" SDTR"); 823 ti = &sc->sc_tinfo[scb->target]; 824 sc->sc_omsg[len++] = MSG_EXTENDED; 825 sc->sc_omsg[len++] = 3; 826 sc->sc_omsg[len++] = MSG_EXT_SDTR; 827 sc->sc_omsg[len++] = ti->period; 828 sc->sc_omsg[len++] = ti->offset; 829 } 830 DPRINTF("\n"); 831 832 MESH_SET_XFER(sc, len); 833 if (len == 1) { 834 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGOUT); 835 mesh_set_reg(sc, MESH_FIFO, sc->sc_omsg[0]); 836 } else { 837 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGOUT | MESH_SEQ_ATN); 838 839 for (i = 0; i < len - 1; i++) 840 mesh_set_reg(sc, MESH_FIFO, sc->sc_omsg[i]); 841 842 /* Wait for the FIFO empty... */ 843 while (mesh_read_reg(sc, MESH_FIFO_COUNT) > 0); 844 845 /* ...then write the last byte. */ 846 mesh_set_reg(sc, MESH_FIFO, sc->sc_omsg[i]); 847 } 848 sc->sc_nextstate = MESH_UNKNOWN; 849 } 850 851 void 852 mesh_bus_reset(sc) 853 struct mesh_softc *sc; 854 { 855 DPRINTF("mesh_bus_reset\n"); 856 857 /* Disable interrupts. */ 858 mesh_set_reg(sc, MESH_INTR_MASK, 0); 859 860 /* Assert RST line. */ 861 mesh_set_reg(sc, MESH_BUS_STATUS1, MESH_STATUS1_RST); 862 delay(50); 863 mesh_set_reg(sc, MESH_BUS_STATUS1, 0); 864 865 mesh_reset(sc); 866 } 867 868 void 869 mesh_reset(sc) 870 struct mesh_softc *sc; 871 { 872 int i; 873 874 DPRINTF("mesh_reset\n"); 875 876 /* Reset DMA first. */ 877 dbdma_reset(sc->sc_dmareg); 878 879 /* Disable interrupts. */ 880 mesh_set_reg(sc, MESH_INTR_MASK, 0); 881 882 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_RESET_MESH); 883 delay(1); 884 885 /* Wait for reset done. */ 886 while (mesh_read_reg(sc, MESH_INTERRUPT) == 0); 887 888 /* Clear interrupts */ 889 mesh_set_reg(sc, MESH_INTERRUPT, 0x7); 890 891 /* Set SCSI ID */ 892 mesh_set_reg(sc, MESH_SOURCE_ID, sc->sc_id); 893 894 /* Set to async mode by default. */ 895 mesh_set_reg(sc, MESH_SYNC_PARAM, 2); 896 897 /* Set selection timeout to 250ms. */ 898 mesh_set_reg(sc, MESH_SEL_TIMEOUT, 250 * sc->sc_freq / 500); 899 900 /* Enable parity check. */ 901 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_ENABLE_PARITY); 902 903 /* Enable all interrupts. */ 904 mesh_set_reg(sc, MESH_INTR_MASK, 0x7); 905 906 for (i = 0; i < 7; i++) { 907 struct mesh_tinfo *ti = &sc->sc_tinfo[i]; 908 909 ti->flags = 0; 910 ti->period = ti->offset = 0; 911 if (sc->sc_cfflags & (0x100 << i)) 912 ti->flags |= T_SYNCNEGO; 913 } 914 sc->sc_nexus = NULL; 915 } 916 917 int 918 mesh_stp(sc, v) 919 struct mesh_softc *sc; 920 int v; 921 { 922 /* 923 * stp(v) = 5 * clock_period (v == 0) 924 * = (v + 2) * 2 clock_period (v > 0) 925 */ 926 927 if (v == 0) 928 return 5 * 250 / sc->sc_freq; 929 else 930 return (v + 2) * 2 * 250 / sc->sc_freq; 931 } 932 933 void 934 mesh_setsync(sc, ti) 935 struct mesh_softc *sc; 936 struct mesh_tinfo *ti; 937 { 938 int period = ti->period; 939 int offset = ti->offset; 940 int v; 941 942 if ((ti->flags & T_SYNCMODE) == 0) 943 offset = 0; 944 945 if (offset == 0) { /* async mode */ 946 mesh_set_reg(sc, MESH_SYNC_PARAM, 2); 947 return; 948 } 949 950 v = period * sc->sc_freq / 250 / 2 - 2; 951 if (v < 0) 952 v = 0; 953 if (mesh_stp(sc, v) < period) 954 v++; 955 if (v > 15) 956 v = 15; 957 mesh_set_reg(sc, MESH_SYNC_PARAM, (offset << 4) | v); 958 } 959 960 struct mesh_scb * 961 mesh_get_scb(sc) 962 struct mesh_softc *sc; 963 { 964 struct mesh_scb *scb; 965 int s; 966 967 s = splbio(); 968 if ((scb = sc->free_scb.tqh_first) != NULL) 969 TAILQ_REMOVE(&sc->free_scb, scb, chain); 970 splx(s); 971 972 return scb; 973 } 974 975 void 976 mesh_free_scb(sc, scb) 977 struct mesh_softc *sc; 978 struct mesh_scb *scb; 979 { 980 int s; 981 982 s = splbio(); 983 TAILQ_INSERT_HEAD(&sc->free_scb, scb, chain); 984 splx(s); 985 } 986 987 void 988 mesh_scsi_request(chan, req, arg) 989 struct scsipi_channel *chan; 990 scsipi_adapter_req_t req; 991 void *arg; 992 { 993 struct scsipi_xfer *xs; 994 struct scsipi_periph *periph; 995 struct mesh_softc *sc = (void *)chan->chan_adapter->adapt_dev; 996 struct mesh_scb *scb; 997 u_int flags; 998 int s; 999 1000 switch (req) { 1001 case ADAPTER_REQ_RUN_XFER: 1002 xs = arg; 1003 periph = xs->xs_periph; 1004 flags = xs->xs_control; 1005 1006 1007 if ((scb = mesh_get_scb(sc)) == NULL) { 1008 xs->error = XS_RESOURCE_SHORTAGE; 1009 scsipi_done(xs); 1010 return; 1011 } 1012 scb->xs = xs; 1013 scb->flags = 0; 1014 scb->status = 0; 1015 scb->daddr = (vaddr_t)xs->data; 1016 scb->dlen = xs->datalen; 1017 scb->resid = xs->datalen; 1018 memcpy(&scb->cmd, xs->cmd, xs->cmdlen); 1019 scb->cmdlen = xs->cmdlen; 1020 scb->target = periph->periph_target; 1021 sc->sc_imsglen = 0; /* XXX ? */ 1022 1023 #ifdef MESH_DEBUG 1024 { 1025 int i; 1026 printf("mesh_scsi_cmd: target = %d, cdb = %02x", 1027 scb->target, scb->cmd.opcode); 1028 for (i = 0; i < 5; i++) 1029 printf(" %02x", scb->cmd.bytes[i]); 1030 printf("\n"); 1031 } 1032 #endif 1033 1034 if (flags & XS_CTL_POLL) 1035 scb->flags |= MESH_POLL; 1036 #if 0 1037 if (flags & XS_CTL_DATA_OUT) 1038 scb->flags &= ~MESH_READ; 1039 #endif 1040 if (flags & XS_CTL_DATA_IN) 1041 scb->flags |= MESH_READ; 1042 1043 s = splbio(); 1044 1045 TAILQ_INSERT_TAIL(&sc->ready_scb, scb, chain); 1046 1047 if (sc->sc_nexus == NULL) /* IDLE */ 1048 mesh_sched(sc); 1049 1050 splx(s); 1051 1052 if ((flags & XS_CTL_POLL) == 0) 1053 return; 1054 1055 if (mesh_poll(sc, xs)) { 1056 printf("%s: timeout\n", sc->sc_dev.dv_xname); 1057 if (mesh_poll(sc, xs)) 1058 printf("%s: timeout again\n", sc->sc_dev.dv_xname); 1059 } 1060 return; 1061 1062 case ADAPTER_REQ_GROW_RESOURCES: 1063 /* XXX Not supported. */ 1064 return; 1065 1066 case ADAPTER_REQ_SET_XFER_MODE: 1067 /* XXX Not supported. */ 1068 return; 1069 } 1070 1071 } 1072 1073 void 1074 mesh_sched(sc) 1075 struct mesh_softc *sc; 1076 { 1077 struct scsipi_xfer *xs; 1078 struct mesh_scb *scb; 1079 1080 scb = sc->ready_scb.tqh_first; 1081 start: 1082 if (scb == NULL) 1083 return; 1084 1085 xs = scb->xs; 1086 1087 if (sc->sc_nexus == NULL) { 1088 TAILQ_REMOVE(&sc->ready_scb, scb, chain); 1089 sc->sc_nexus = scb; 1090 mesh_select(sc, scb); 1091 return; 1092 } 1093 1094 scb = scb->chain.tqe_next; 1095 goto start; 1096 } 1097 1098 int 1099 mesh_poll(sc, xs) 1100 struct mesh_softc *sc; 1101 struct scsipi_xfer *xs; 1102 { 1103 int count = xs->timeout; 1104 1105 while (count) { 1106 if (mesh_read_reg(sc, MESH_INTERRUPT)) 1107 mesh_intr(sc); 1108 1109 if (xs->xs_status & XS_STS_DONE) 1110 return 0; 1111 delay(1000); 1112 count--; 1113 }; 1114 return 1; 1115 } 1116 1117 void 1118 mesh_done(sc, scb) 1119 struct mesh_softc *sc; 1120 struct mesh_scb *scb; 1121 { 1122 struct scsipi_xfer *xs = scb->xs; 1123 1124 DPRINTF("mesh_done\n"); 1125 1126 sc->sc_nextstate = MESH_BUSFREE; 1127 sc->sc_nexus = NULL; 1128 1129 callout_stop(&scb->xs->xs_callout); 1130 1131 if (scb->status == SCSI_BUSY) { 1132 xs->error = XS_BUSY; 1133 printf("Target busy\n"); 1134 } 1135 1136 xs->status = scb->status; 1137 xs->resid = scb->resid; 1138 if (scb->status == SCSI_CHECK) { 1139 xs->error = XS_BUSY; 1140 } 1141 1142 mesh_set_reg(sc, MESH_SYNC_PARAM, 2); 1143 1144 if ((xs->xs_control & XS_CTL_POLL) == 0) 1145 mesh_sched(sc); 1146 1147 scsipi_done(xs); 1148 mesh_free_scb(sc, scb); 1149 } 1150 1151 void 1152 mesh_timeout(arg) 1153 void *arg; 1154 { 1155 struct mesh_scb *scb = arg; 1156 struct mesh_softc *sc = 1157 (void *)scb->xs->xs_periph->periph_channel->chan_adapter->adapt_dev; 1158 int s; 1159 int status0, status1; 1160 int intr, error, exception, imsk; 1161 1162 printf("%s: timeout state %d\n", sc->sc_dev.dv_xname, sc->sc_nextstate); 1163 1164 intr = mesh_read_reg(sc, MESH_INTERRUPT); 1165 imsk = mesh_read_reg(sc, MESH_INTR_MASK); 1166 exception = mesh_read_reg(sc, MESH_EXCEPTION); 1167 error = mesh_read_reg(sc, MESH_ERROR); 1168 status0 = mesh_read_reg(sc, MESH_BUS_STATUS0); 1169 status1 = mesh_read_reg(sc, MESH_BUS_STATUS1); 1170 1171 printf("%s: intr/msk %02x/%02x, exc %02x, err %02x, st0/1 %02x/%02x\n", 1172 sc->sc_dev.dv_xname, 1173 intr, imsk, exception, error, status0, status1); 1174 1175 s = splbio(); 1176 if (sc->sc_flags & MESH_DMA_ACTIVE) { 1177 printf("mesh: resetting DMA\n"); 1178 dbdma_reset(sc->sc_dmareg); 1179 } 1180 scb->xs->error = XS_TIMEOUT; 1181 1182 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE); 1183 sc->sc_nextstate = MESH_COMPLETE; 1184 1185 splx(s); 1186 } 1187 1188 void 1189 mesh_minphys(bp) 1190 struct buf *bp; 1191 { 1192 if (bp->b_bcount > 64*1024) 1193 bp->b_bcount = 64*1024; 1194 1195 minphys(bp); 1196 } 1197