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