1 /* $NetBSD: sci.c,v 1.28 2003/06/18 08:58:36 drochner Exp $ */ 2 3 /* 4 * Copyright (c) 1994 Michael L. Hitch 5 * Copyright (c) 1990 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Van Jacobson of Lawrence Berkeley Laboratory. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * @(#)scsi.c 7.5 (Berkeley) 5/4/91 40 */ 41 42 /* 43 * AMIGA NCR 5380 scsi adaptor driver 44 */ 45 46 #include <sys/cdefs.h> 47 __KERNEL_RCSID(0, "$NetBSD: sci.c,v 1.28 2003/06/18 08:58:36 drochner Exp $"); 48 49 #include <sys/param.h> 50 #include <sys/systm.h> 51 #include <sys/device.h> 52 #include <sys/disklabel.h> 53 #include <sys/buf.h> 54 #include <dev/scsipi/scsi_all.h> 55 #include <dev/scsipi/scsipi_all.h> 56 #include <dev/scsipi/scsiconf.h> 57 #include <uvm/uvm_extern.h> 58 #include <machine/pmap.h> 59 #include <machine/cpu.h> 60 #include <amiga/amiga/device.h> 61 #include <amiga/amiga/custom.h> 62 #include <amiga/amiga/isr.h> 63 #include <amiga/dev/scireg.h> 64 #include <amiga/dev/scivar.h> 65 66 /* 67 * SCSI delays 68 * In u-seconds, primarily for state changes on the SPC. 69 */ 70 #define SCI_CMD_WAIT 50000 /* wait per step of 'immediate' cmds */ 71 #define SCI_DATA_WAIT 50000 /* wait per data in/out step */ 72 #define SCI_INIT_WAIT 50000 /* wait per step (both) during init */ 73 74 int sciicmd(struct sci_softc *, int, void *, int, void *, int,u_char); 75 int scigo(struct sci_softc *, struct scsipi_xfer *); 76 int sciselectbus(struct sci_softc *, u_char, u_char); 77 void sciabort(struct sci_softc *, char *); 78 void scierror(struct sci_softc *, u_char); 79 void scisetdelay(int); 80 void sci_scsidone(struct sci_softc *, int); 81 void sci_donextcmd(struct sci_softc *); 82 int sci_ixfer_out(struct sci_softc *, int, register u_char *, int); 83 void sci_ixfer_in(struct sci_softc *, int, register u_char *, int); 84 85 int sci_cmd_wait = SCI_CMD_WAIT; 86 int sci_data_wait = SCI_DATA_WAIT; 87 int sci_init_wait = SCI_INIT_WAIT; 88 89 int sci_no_dma = 0; 90 91 #ifdef DEBUG 92 #define QPRINTF(a) if (sci_debug > 1) printf a 93 int sci_debug = 0; 94 #else 95 #define QPRINTF(a) 96 #endif 97 98 /* 99 * default minphys routine for sci based controllers 100 */ 101 void 102 sci_minphys(struct buf *bp) 103 { 104 105 /* 106 * No max transfer at this level. 107 */ 108 minphys(bp); 109 } 110 111 /* 112 * used by specific sci controller 113 * 114 * it appears that the higher level code does nothing with LUN's 115 * so I will too. I could plug it in, however so could they 116 * in scsi_scsipi_cmd(). 117 */ 118 void 119 sci_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, 120 void *arg) 121 { 122 struct scsipi_xfer *xs; 123 struct scsipi_periph *periph; 124 struct sci_softc *dev = (void *)chan->chan_adapter->adapt_dev; 125 int flags, s; 126 127 switch (req) { 128 case ADAPTER_REQ_RUN_XFER: 129 xs = arg; 130 periph = xs->xs_periph; 131 flags = xs->xs_control; 132 133 if (flags & XS_CTL_DATA_UIO) 134 panic("sci: scsi data uio requested"); 135 136 if (dev->sc_xs && flags & XS_CTL_POLL) 137 panic("sci_scsicmd: busy"); 138 139 #ifdef DIAGNOSTIC 140 /* 141 * This should never happen as we track the resources 142 * in the mid-layer. 143 */ 144 if (dev->sc_xs) { 145 scsipi_printaddr(periph); 146 printf("unable to allocate scb\n"); 147 panic("sea_scsipi_request"); 148 } 149 #endif 150 151 dev->sc_xs = xs; 152 splx(s); 153 154 /* 155 * nothing is pending do it now. 156 */ 157 sci_donextcmd(dev); 158 159 return; 160 161 case ADAPTER_REQ_GROW_RESOURCES: 162 return; 163 164 case ADAPTER_REQ_SET_XFER_MODE: 165 return; 166 } 167 } 168 169 /* 170 * entered with dev->sc_xs pointing to the next xfer to perform 171 */ 172 void 173 sci_donextcmd(struct sci_softc *dev) 174 { 175 struct scsipi_xfer *xs; 176 struct scsipi_periph *periph; 177 int flags, phase, stat; 178 179 xs = dev->sc_xs; 180 periph = xs->xs_periph; 181 flags = xs->xs_control; 182 183 if (flags & XS_CTL_DATA_IN) 184 phase = DATA_IN_PHASE; 185 else if (flags & XS_CTL_DATA_OUT) 186 phase = DATA_OUT_PHASE; 187 else 188 phase = STATUS_PHASE; 189 190 if (flags & XS_CTL_RESET) 191 scireset(dev); 192 193 dev->sc_stat[0] = -1; 194 xs->cmd->bytes[0] |= periph->periph_lun << 5; 195 if (phase == STATUS_PHASE || flags & XS_CTL_POLL) 196 stat = sciicmd(dev, periph->periph_target, xs->cmd, xs->cmdlen, 197 xs->data, xs->datalen, phase); 198 else if (scigo(dev, xs) == 0) 199 return; 200 else 201 stat = dev->sc_stat[0]; 202 203 sci_scsidone(dev, stat); 204 } 205 206 void 207 sci_scsidone(struct sci_softc *dev, int stat) 208 { 209 struct scsipi_xfer *xs; 210 211 xs = dev->sc_xs; 212 #ifdef DIAGNOSTIC 213 if (xs == NULL) 214 panic("sci_scsidone"); 215 #endif 216 xs->status = stat; 217 if (stat == 0) 218 xs->resid = 0; 219 else { 220 switch(stat) { 221 case SCSI_CHECK: 222 xs->resid = 0; 223 /* FALLTHOUGH */ 224 case SCSI_BUSY: 225 xs->error = XS_BUSY; 226 break; 227 default: 228 xs->error = XS_DRIVER_STUFFUP; 229 QPRINTF(("sci_scsicmd() bad %x\n", stat)); 230 break; 231 } 232 } 233 234 scsipi_done(xs); 235 236 } 237 238 void 239 sciabort(struct sci_softc *dev, char *where) 240 { 241 printf ("%s: abort %s: csr = 0x%02x, bus = 0x%02x\n", 242 dev->sc_dev.dv_xname, where, *dev->sci_csr, *dev->sci_bus_csr); 243 244 if (dev->sc_flags & SCI_SELECTED) { 245 246 /* lets just hope it worked.. */ 247 dev->sc_flags &= ~SCI_SELECTED; 248 /* XXX */ 249 scireset (dev); 250 } 251 } 252 253 /* 254 * XXX Set/reset long delays. 255 * 256 * if delay == 0, reset default delays 257 * if delay < 0, set both delays to default long initialization values 258 * if delay > 0, set both delays to this value 259 * 260 * Used when a devices is expected to respond slowly (e.g. during 261 * initialization). 262 */ 263 void 264 scisetdelay(int del) 265 { 266 static int saved_cmd_wait, saved_data_wait; 267 268 if (del) { 269 saved_cmd_wait = sci_cmd_wait; 270 saved_data_wait = sci_data_wait; 271 if (del > 0) 272 sci_cmd_wait = sci_data_wait = del; 273 else 274 sci_cmd_wait = sci_data_wait = sci_init_wait; 275 } else { 276 sci_cmd_wait = saved_cmd_wait; 277 sci_data_wait = saved_data_wait; 278 } 279 } 280 281 void 282 scireset(struct sci_softc *dev) 283 { 284 u_int s; 285 u_char my_id; 286 287 dev->sc_flags &= ~SCI_SELECTED; 288 if (dev->sc_flags & SCI_ALIVE) 289 sciabort(dev, "reset"); 290 291 printf("%s: ", dev->sc_dev.dv_xname); 292 293 s = splbio(); 294 /* preserve our ID for now */ 295 my_id = 7; 296 297 /* 298 * Reset the chip 299 */ 300 *dev->sci_icmd = SCI_ICMD_TEST; 301 *dev->sci_icmd = SCI_ICMD_TEST | SCI_ICMD_RST; 302 delay (25); 303 *dev->sci_icmd = 0; 304 305 /* 306 * Set up various chip parameters 307 */ 308 *dev->sci_icmd = 0; 309 *dev->sci_tcmd = 0; 310 *dev->sci_sel_enb = 0; 311 312 /* anything else was zeroed by reset */ 313 314 splx (s); 315 316 printf("sci id %d\n", my_id); 317 dev->sc_flags |= SCI_ALIVE; 318 } 319 320 void 321 scierror(struct sci_softc *dev, u_char csr) 322 { 323 struct scsipi_xfer *xs; 324 325 xs = dev->sc_xs; 326 327 #ifdef DIAGNOSTIC 328 if (xs == NULL) 329 panic("scierror"); 330 #endif 331 if (xs->xs_control & XS_CTL_SILENT) 332 return; 333 334 printf("%s: ", dev->sc_dev.dv_xname); 335 printf("csr == 0x%02i\n", csr); /* XXX */ 336 } 337 338 /* 339 * select the bus, return when selected or error. 340 */ 341 int 342 sciselectbus(struct sci_softc *dev, u_char target, u_char our_addr) 343 { 344 register int timeo = 2500; 345 346 QPRINTF (("sciselectbus %d\n", target)); 347 348 /* if we're already selected, return */ 349 if (dev->sc_flags & SCI_SELECTED) /* XXXX */ 350 return 1; 351 352 if ((*dev->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) && 353 (*dev->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) && 354 (*dev->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL))) 355 return 1; 356 357 *dev->sci_tcmd = 0; 358 *dev->sci_odata = 0x80 + (1 << target); 359 *dev->sci_icmd = SCI_ICMD_DATA|SCI_ICMD_SEL; 360 while ((*dev->sci_bus_csr & SCI_BUS_BSY) == 0) { 361 if (--timeo > 0) { 362 delay(100); 363 } else { 364 break; 365 } 366 } 367 if (timeo) { 368 *dev->sci_icmd = 0; 369 dev->sc_flags |= SCI_SELECTED; 370 return (0); 371 } 372 *dev->sci_icmd = 0; 373 return (1); 374 } 375 376 int 377 sci_ixfer_out(register struct sci_softc *dev, int len, register u_char *buf, 378 int phase) 379 { 380 register int wait = sci_data_wait; 381 u_char csr; 382 383 QPRINTF(("sci_ixfer_out {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 384 len, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], 385 buf[6], buf[7], buf[8], buf[9])); 386 387 *dev->sci_tcmd = phase; 388 *dev->sci_icmd = SCI_ICMD_DATA; 389 for (;len > 0; len--) { 390 csr = *dev->sci_bus_csr; 391 while (!(csr & SCI_BUS_REQ)) { 392 if ((csr & SCI_BUS_BSY) == 0 || --wait < 0) { 393 #ifdef DEBUG 394 if (sci_debug) 395 printf("sci_ixfer_out fail: l%d i%x w%d\n", 396 len, csr, wait); 397 #endif 398 return (len); 399 } 400 delay(1); 401 csr = *dev->sci_bus_csr; 402 } 403 404 if (!(*dev->sci_csr & SCI_CSR_PHASE_MATCH)) 405 break; 406 *dev->sci_odata = *buf; 407 *dev->sci_icmd = SCI_ICMD_DATA|SCI_ICMD_ACK; 408 buf++; 409 while (*dev->sci_bus_csr & SCI_BUS_REQ); 410 *dev->sci_icmd = SCI_ICMD_DATA; 411 } 412 413 QPRINTF(("sci_ixfer_out done\n")); 414 return (0); 415 } 416 417 void 418 sci_ixfer_in(struct sci_softc *dev, int len, register u_char *buf, int phase) 419 { 420 int wait = sci_data_wait; 421 u_char csr; 422 volatile register u_char *sci_bus_csr = dev->sci_bus_csr; 423 volatile register u_char *sci_data = dev->sci_data; 424 volatile register u_char *sci_icmd = dev->sci_icmd; 425 #ifdef DEBUG 426 u_char *obp = buf; 427 #endif 428 429 csr = *sci_bus_csr; 430 431 QPRINTF(("sci_ixfer_in %d, csr=%02x\n", len, csr)); 432 433 *dev->sci_tcmd = phase; 434 *sci_icmd = 0; 435 for (;len > 0; len--) { 436 csr = *sci_bus_csr; 437 while (!(csr & SCI_BUS_REQ)) { 438 if (!(csr & SCI_BUS_BSY) || --wait < 0) { 439 #ifdef DEBUG 440 if (sci_debug) 441 printf("sci_ixfer_in fail: l%d i%x w%d\n", 442 len, csr, wait); 443 #endif 444 return; 445 } 446 447 delay(1); 448 csr = *sci_bus_csr; 449 } 450 451 if (!(*dev->sci_csr & SCI_CSR_PHASE_MATCH)) 452 break; 453 *buf = *sci_data; 454 *sci_icmd = SCI_ICMD_ACK; 455 buf++; 456 while (*sci_bus_csr & SCI_BUS_REQ); 457 *sci_icmd = 0; 458 } 459 460 QPRINTF(("sci_ixfer_in {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 461 len, obp[0], obp[1], obp[2], obp[3], obp[4], obp[5], 462 obp[6], obp[7], obp[8], obp[9])); 463 } 464 465 /* 466 * SCSI 'immediate' command: issue a command to some SCSI device 467 * and get back an 'immediate' response (i.e., do programmed xfer 468 * to get the response data). 'cbuf' is a buffer containing a scsi 469 * command of length clen bytes. 'buf' is a buffer of length 'len' 470 * bytes for data. The transfer direction is determined by the device 471 * (i.e., by the scsi bus data xfer phase). If 'len' is zero, the 472 * command must supply no data. 'xferphase' is the bus phase the 473 * caller expects to happen after the command is issued. It should 474 * be one of DATA_IN_PHASE, DATA_OUT_PHASE or STATUS_PHASE. 475 */ 476 int 477 sciicmd(struct sci_softc *dev, int target, void *cbuf, int clen, void *buf, 478 int len, u_char xferphase) 479 { 480 u_char phase; 481 register int wait; 482 483 /* select the SCSI bus (it's an error if bus isn't free) */ 484 if (sciselectbus (dev, target, dev->sc_scsi_addr)) 485 return -1; 486 /* 487 * Wait for a phase change (or error) then let the device 488 * sequence us through the various SCSI phases. 489 */ 490 dev->sc_stat[0] = 0xff; 491 dev->sc_msg[0] = 0xff; 492 phase = CMD_PHASE; 493 while (1) { 494 wait = sci_cmd_wait; 495 496 while ((*dev->sci_bus_csr & (SCI_BUS_REQ|SCI_BUS_BSY)) == SCI_BUS_BSY); 497 498 QPRINTF((">CSR:%02x<", *dev->sci_bus_csr)); 499 if ((*dev->sci_bus_csr & SCI_BUS_REQ) == 0) { 500 return -1; 501 } 502 phase = SCI_PHASE(*dev->sci_bus_csr); 503 504 switch (phase) { 505 case CMD_PHASE: 506 if (sci_ixfer_out (dev, clen, cbuf, phase)) 507 goto abort; 508 phase = xferphase; 509 break; 510 511 case DATA_IN_PHASE: 512 if (len <= 0) 513 goto abort; 514 wait = sci_data_wait; 515 sci_ixfer_in (dev, len, buf, phase); 516 phase = STATUS_PHASE; 517 break; 518 519 case DATA_OUT_PHASE: 520 if (len <= 0) 521 goto abort; 522 wait = sci_data_wait; 523 if (sci_ixfer_out (dev, len, buf, phase)) 524 goto abort; 525 phase = STATUS_PHASE; 526 break; 527 528 case MESG_IN_PHASE: 529 dev->sc_msg[0] = 0xff; 530 sci_ixfer_in (dev, 1, dev->sc_msg,phase); 531 dev->sc_flags &= ~SCI_SELECTED; 532 while (*dev->sci_bus_csr & SCI_BUS_BSY); 533 goto out; 534 break; 535 536 case MESG_OUT_PHASE: 537 phase = STATUS_PHASE; 538 break; 539 540 case STATUS_PHASE: 541 sci_ixfer_in (dev, 1, dev->sc_stat, phase); 542 phase = MESG_IN_PHASE; 543 break; 544 545 case BUS_FREE_PHASE: 546 goto out; 547 548 default: 549 printf("sci: unexpected phase %d in icmd from %d\n", 550 phase, target); 551 goto abort; 552 } 553 #if 0 554 if (wait <= 0) 555 goto abort; 556 #endif 557 } 558 559 abort: 560 sciabort(dev, "icmd"); 561 out: 562 QPRINTF(("=STS:%02x=", dev->sc_stat[0])); 563 return (dev->sc_stat[0]); 564 } 565 566 int 567 scigo(struct sci_softc *dev, struct scsipi_xfer *xs) 568 { 569 int count, target; 570 u_char phase, *addr; 571 572 target = xs->xs_periph->periph_target; 573 count = xs->datalen; 574 addr = xs->data; 575 576 if (sci_no_dma) { 577 sciicmd (dev, target, (u_char *) xs->cmd, xs->cmdlen, 578 addr, count, 579 xs->xs_control & XS_CTL_DATA_IN ? DATA_IN_PHASE : DATA_OUT_PHASE); 580 581 return (1); 582 } 583 584 /* select the SCSI bus (it's an error if bus isn't free) */ 585 if (sciselectbus (dev, target, dev->sc_scsi_addr)) 586 return -1; 587 /* 588 * Wait for a phase change (or error) then let the device 589 * sequence us through the various SCSI phases. 590 */ 591 dev->sc_stat[0] = 0xff; 592 dev->sc_msg[0] = 0xff; 593 phase = CMD_PHASE; 594 while (1) { 595 while ((*dev->sci_bus_csr & (SCI_BUS_REQ|SCI_BUS_BSY)) == 596 SCI_BUS_BSY); 597 598 QPRINTF((">CSR:%02x<", *dev->sci_bus_csr)); 599 if ((*dev->sci_bus_csr & SCI_BUS_REQ) == 0) { 600 goto abort; 601 } 602 phase = SCI_PHASE(*dev->sci_bus_csr); 603 604 switch (phase) { 605 case CMD_PHASE: 606 if (sci_ixfer_out (dev, xs->cmdlen, (u_char *) xs->cmd, phase)) 607 goto abort; 608 phase = xs->xs_control & XS_CTL_DATA_IN ? DATA_IN_PHASE : DATA_OUT_PHASE; 609 break; 610 611 case DATA_IN_PHASE: 612 if (count <= 0) 613 goto abort; 614 /* XXX use psuedo DMA if available */ 615 if (count >= 128 && dev->dma_xfer_in) 616 (*dev->dma_xfer_in)(dev, count, addr, phase); 617 else 618 sci_ixfer_in (dev, count, addr, phase); 619 phase = STATUS_PHASE; 620 break; 621 622 case DATA_OUT_PHASE: 623 if (count <= 0) 624 goto abort; 625 /* XXX use psuedo DMA if available */ 626 if (count >= 128 && dev->dma_xfer_out) 627 (*dev->dma_xfer_out)(dev, count, addr, phase); 628 else 629 if (sci_ixfer_out (dev, count, addr, phase)) 630 goto abort; 631 phase = STATUS_PHASE; 632 break; 633 634 case MESG_IN_PHASE: 635 dev->sc_msg[0] = 0xff; 636 sci_ixfer_in (dev, 1, dev->sc_msg,phase); 637 dev->sc_flags &= ~SCI_SELECTED; 638 while (*dev->sci_bus_csr & SCI_BUS_BSY); 639 goto out; 640 break; 641 642 case MESG_OUT_PHASE: 643 phase = STATUS_PHASE; 644 break; 645 646 case STATUS_PHASE: 647 sci_ixfer_in (dev, 1, dev->sc_stat, phase); 648 phase = MESG_IN_PHASE; 649 break; 650 651 case BUS_FREE_PHASE: 652 goto out; 653 654 default: 655 printf("sci: unexpected phase %d in icmd from %d\n", 656 phase, target); 657 goto abort; 658 } 659 } 660 661 abort: 662 sciabort(dev, "go"); 663 out: 664 QPRINTF(("=STS:%02x=", dev->sc_stat[0])); 665 return (1); 666 } 667