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